Compare commits

...

866 Commits

Author SHA1 Message Date
renovate[bot] 9034a8ddfa fix(deps): update module github.com/meilisearch/meilisearch-go to v0.36.3 2026-10-05 18:39:41 +00:00
naiy_ 4c39bbe9c2 fix(drivers/189pc): align login with the official PC client (#3105)
QR code scans were authorized on the phone but the storage stayed stuck on
the QR page, and token-only setups failed with "params is null".

The driver used appId 8025431004 while the official PC client uses
9317140619. Tokens, sessions and QR sessions are all scoped to an appId, so
the mismatch meant the QR poll never saw status:0 and an accessToken could
not be exchanged for a sessionSecret.

- Use appId 9317140619 and version 7.2.4.0. QR state polling uses
  clientType=1; password login keeps 10020.
- Send the QR poll parameters the official client sends (cb_SaveName,
  isOauth2, state, user-finger header, logbox Referer) and poll locally
  instead of only checking once per save.
- Parse lt/reqId from the logbox redirect and paramId from appConf.do. The
  new login page no longer embeds them as inline variables; the old inline
  format is still supported.
- Implement the -133 second device verification via
  sendSmsCodeForSecondAuth/submitForSecondAuth. That endpoint has no
  dedicated SMS field: the code goes into epd, encrypted with the same
  public key used for the password. Persist the DEVICEID cookie so the
  verification only happens once.
- Detect refreshToken.do failures. It reports them as HTTP 200 with a
  result field, so SetError never fired and a failed refresh was treated as
  success, surfacing later as a misleading "params is null".
- username/password are no longer required, so token-only storages save
  without placeholders. clientSn/jgOpenId are optional and only sent when
  configured; user-finger is generated once per storage.
- Return named errors instead of panicking when the login page changes shape.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-03 15:45:29 +08:00
帅丘 e1d88b071f fix(drivers/lanzou): support new /fn download page structure (#3157)
Lanzou recently changed the file share page: download params moved
into an iframe (/fn?<token>) inner page, and the download API is now
an absolute URL (https://apifile.woozooo.com/ajaxfile.php?file=N)
with new sign params (wp_sign/ajaxdata, action=downprocess).

The old findFileIDReg ('/ajaxm.php?file=N' relative path) no longer
matches, causing 'failed link: failed get link: not find file id'.

Fall back to parsing the new /fn page structure when the legacy
regex does not match. Legacy flow is kept untouched.

Signed-off-by: rzsgsfm <rzsgsfm@users.noreply.github.com>
Co-authored-by: rzsgsfm <rzsgsfm@users.noreply.github.com>
Co-authored-by: GLM (ZCode CLI) <noreply@z.ai>
2026-10-03 14:50:51 +08:00
ILoveScratch ea10624fb6 fix: harden request handling for files, search, proxy and SSO
Co-authored-by: PIKACHUIM <PIKACHUIM@users.noreply.github.com>
2026-09-29 19:05:50 +08:00
ILoveScratch 54ae9d7451 fix(internal/db/searchnode): fix index update path (#3128) 2026-09-24 19:25:29 +08:00
Yinan Qin c16701b94b fix(build): update cgo-actions version to v1.3.0 and fallback FreeBSD version to 14.4 (#3130) 2026-09-24 19:23:21 +08:00
Nostalgia 893457cd50 fix(aliyundrive): limit callback concurrency (#3071)
* fix(aliyundrive): limit callback concurrency

- Share proxy callback admission by Aliyun user identity and hold permits for complete response-body lifetimes.
- Retry only verified callback-capacity rejections while preserving direct redirects and server download limiting.
- Map exhausted temporary capacity to S3 SlowDown through the merged OpenListTeam gofakes3 module.
- Cover shared limits, lifecycle release, cancellation, retry classification, and the S3 HTTP response.

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

# Conflicts:
#	go.mod
#	go.sum
#	server/s3/pager.go

* fix(op): separate redirect and proxy link cache entries

- Include redirect mode in the link cache key for all drivers.

- Cover both redirect-to-proxy and proxy-to-redirect cache reuse.

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

* fix(proxy): close range bodies before opening next

- make ServeHTTP own each range body and preserve cleanup failures
- remove the aggregate range closer and pass range readers directly
- replace the obsolete callback transport test with focused lifecycle coverage

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

---------

Co-authored-by: nostalume <nostalucent@gmail.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-09-24 12:01:50 +08:00
Nostalgia 90acfa18e4 refactor(context): centralize request origin access (#3100) 2026-09-24 01:57:21 +08:00
Nostalgia 1462d63a48 fix(net): preserve cancellation errors during partitioned downloads (#3090) 2026-09-24 01:47:30 +08:00
spark cadbf87246 fix(teldrive): use a valid root path for listings (#3108) 2026-09-24 01:46:35 +08:00
ZRHan 9de3f69b8f fix(fs): only list parent dir for related objs when file is video (#3113) 2026-09-24 01:46:14 +08:00
Wray e73a80c78c feat(drivers/pikpak): auto re-login with username/password when tokens expire (#3001) 2026-09-24 01:29:56 +08:00
ZRHan 6c6009109f fix(fs): return FOLDER type for directories in fs/get responses (#3114) 2026-09-24 01:26:42 +08:00
Nostalgia b51d1c8284 fix(s3): close ranged response bodies (#3095) 2026-09-24 01:26:26 +08:00
ILoveScratch f286862c61 refactor(stream): index parked readers by offset instead of full scans (#3048) 2026-09-24 01:25:57 +08:00
awaae 40f4f6546f fix(ftp): handle EOF and detect content type from read bytes (#3125) 2026-09-24 01:20:20 +08:00
Nostalgia 3a31b438a9 refactor(offline): centralize native tool setup (#3096)
- Keep storage-to-tool identity in the offline tool package.
- Share settings persistence, tool initialization, and storage admission across handlers.
- Preserve endpoint payloads and unsupported-storage diagnostics with focused tests.

Co-authored-by: nostalume <nostalucent@gmail.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-09-21 16:54:22 +08:00
Nostalgia 56064d1981 fix(op): enforce link cache lifecycle policy (#3101)
- Share one admitted lifecycle policy between regular and archive links.
- Reject and release links that combine TTL caching with owned resources.
- Keep wrapper clones independent from the source cache expiration.
- Cover reuse, reference, invalidation, conflict, and clone behavior.

Co-authored-by: nostalume <nostalucent@gmail.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-09-21 16:54:12 +08:00
Ziheng Mao d894a3983b fix(115_open): refresh expired OSS credentials during upload (#3063)
- Refresh OSS credentials and retry the rejected multipart operation
- Preserve upload IDs, completed parts, callbacks, and outer part retries
- Rewind parts before resending and pass the upload context to OSS requests

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-09-21 10:38:14 +08:00
ShenLin 084c008102 chore(build): replace uncontrolled email domain (#3103)
- Use the controlled oplist.org domain for embedded build authors
- Update shell and release workflow build metadata

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-09-20 14:25:20 +08:00
Fighting 4580c4db33 fix(alist_v3): set child paths so nested directories resolve (#3019)
* fix(alist_v3): set child paths so nested directories resolve

- Set `Path` on every object returned by `List`, matching the OpenList
  driver. `op.Get` hands a child object straight back to `List`, so a
  child without a path made the driver request `""` from the upstream
  server, which answered with its own root: every directory below the
  mount point served the same listing back, endlessly.
- Add tests covering the child paths and a three-level descent.

Co-authored-by: Claude <81847+claude@users.noreply.github.com>

* test(alist_v3): trim the child-path test to a single case

Collapse the two tests into one two-level descent, drop the recorder
type and the helper funcs, and inline the driver setup. 173 -> 65 lines.

Co-authored-by: Claude <81847+claude@users.noreply.github.com>

---------

Co-authored-by: Fighting <3899648+Elity@users.noreply.github.com>
Co-authored-by: Claude <81847+claude@users.noreply.github.com>
2026-09-15 23:13:10 +08:00
Nostalgia 5447ecb072 fix(s3): encode multipart fixture paths (#3074)
test(s3): encode multipart fixture paths

- Serialize the Local storage addition instead of interpolating filesystem paths into JSON.
- Keep multipart fixture behavior portable across Windows and Linux.

Co-authored-by: nostalume <nostalucent@gmail.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-09-14 20:30:17 +08:00
flyingrtx f18b4acc76 feat(local): add PDF thumbnails on macOS (#3017)
- add an opt-in Local driver setting for PDF thumbnails
- render PDF first pages with macOS Quick Look
- preserve unsupported-platform behavior and cover the renderer with tests

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Co-authored-by: ILoveScratch <ilovescratch@foxmail.com>
2026-09-10 19:45:24 +08:00
fryeggs d6109a7940 feat(task): persist task timestamps across restarts (#2914)
Co-authored-by: OpenAI Codex <noreply@openai.com>
2026-09-10 19:20:11 +08:00
ShenLin 0463da4034 chore(ci): enforce AI disclosures and lock invalid issues (#3059)
ci(github): enforce AI disclosures and lock invalid issues

- Require exactly one AI disclosure option and a model name when AI is used
- Comment, close, lock, and label issues invalid for missing or malformed AI disclosures or missing model names
- Lock issues closed for unchanged placeholder titles
- Lock issues closed for selecting the unread checklist option
- Exclude AI disclosure options from unchecked task detection
- Skip automatic checks for announcement titles
- Update bilingual closure replies to mention locking and request a new issue
- Split issue replies and PR title checks into separate workflows without changing PR title rules

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-09-08 15:20:36 +08:00
Pikachu Ren 2d51c9ab4b feat!(init): add initialization wizard (#3041)
feat: add system initialization (setup wizard) support

Co-authored-by: PIKACHUIM <PIKACHUIM@users.noreply.github.com>
2026-09-07 14:14:22 +08:00
ShenLin d9d8aa24e6 fix(s3): default upload content types and return partial content (#3053)
- Default missing upload MIME types to application/octet-stream before passing streams to storage drivers.
- Return HTTP 206 for successful ranged GET responses while preserving error statuses.
- Add isolated response-status regression tests without database initialization.

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-09-07 12:01:15 +08:00
ShenLin 55530ff171 fix(release): fetch frontend assets from edge (#3052)
- Fetch frontend prerelease assets from edge after release immutability was accidentally enabled for rolling.

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-09-07 12:00:50 +08:00
MadDogOwner 6247cf7be2 feat(server/s3): support multipart upload (#2813) 2026-09-05 15:56:40 +08:00
renovate[bot] eee910babb fix(deps): update module github.com/rclone/rclone to v1.75.1 (#3035)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-05 12:22:53 +08:00
renovate[bot] 6b55a82ffe chore(deps): update docker/setup-qemu-action digest to 1f40c72 (#3021)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-05 12:14:09 +08:00
renovate[bot] 93dac1655f chore(deps): update go toolchain directive to v1.27.1 (#3024)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-05 12:12:51 +08:00
Pikachu Ren 6ad44605c0 feat(drivers/guangyapan): add md5-based instant upload support (#3034)
feat(guangyapan): add md5-based instant upload support

Co-authored-by: PIKACHUIM <PIKACHUIM@users.noreply.github.com>
2026-09-05 12:11:51 +08:00
UcnacDx2 d90d84906e fix(drivers/139): improve mail login credential renewal (#3029)
* fix(drivers/139): improve mail login credential renewal

* fix(drivers/139): guard mail login client initialization

Fall back to base.NewRestyClient() when base.RestyClient has not been initialized, while preserving cloned global-client behavior and the login/SMS retry and redirect policies.
2026-09-05 11:55:41 +08:00
ShenLin c3d3da9286 fix(drivers/189): decode JSON strings before parsing timestamps (#3033)
- Decode JSON time strings before normalizing Unicode spaces in both 189 drivers
- Exercise escaped spaces and existing date formats through JSON unmarshalling
- Cover invalid JSON input and XML time parsing

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-09-05 00:12:20 +08:00
renovate[bot] 2bdf16d596 chore(deps): pin dependencies (#2736)
* chore(deps): pin dependencies

* chore: exclude docker from renovate

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Yinan Qin <elysia-best@simplelinux.cn.eu.org>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-09-01 22:58:15 +08:00
renovate[bot] f8ebaec4f1 fix(deps): update module google.golang.org/grpc to v1.85.0-dev (#3015)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-01 22:58:10 +08:00
renovate[bot] fc23f4e781 fix(deps): update module github.com/shirou/gopsutil/v4 to v4.26.8 (#3014)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-01 22:58:05 +08:00
renovate[bot] 3ea9984aea fix(deps): update module golang.org/x/image to v0.45.0 (#2994)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-01 22:58:00 +08:00
renovate[bot] cc11f354f1 fix(deps): update module github.com/go-webauthn/webauthn to v0.18.0 (#2988)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-09-01 22:57:54 +08:00
renovate[bot] 8869874b76 fix(deps): update module github.com/bmatcuk/doublestar/v4 to v4.10.0 (#2987)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-01 22:57:48 +08:00
ShenLin 523af855ba fix(auth): secure SSO account binding
- Issue and verify short-lived SSO binding state and proof tokens
- Bind provider callbacks to an HttpOnly browser session cookie
- Reject invalid or already-associated SSO identities during profile updates

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
2026-09-01 18:45:40 +08:00
ShenLin bba3516693 fix(upload): authorize direct upload destinations
- Resolve and authorize the canonical destination from the request payload
- Reject upload capabilities that cross virtual storage mount boundaries
- Remove the unrelated File-Path middleware authorization check

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
2026-09-01 18:45:39 +08:00
ShenLin f244adf60e fix(meta): enforce case-insensitive access controls
- Add an invalidated metadata snapshot for case-insensitive fallback lookups
- Enforce segment-aware metadata coverage for passwords and download signatures
- Add regression tests while preserving case-sensitive write authorization

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
2026-09-01 18:45:39 +08:00
abcqqoo ce87b45d2d fix(cmd/start): use absolute executable path for child process (#2125)
* fix(cmd/start): use absolute executable path for child process

* fix(cmd/start): detect force-bin-dir flag variants

---------

Co-authored-by: Zoe Lee <zoelee@gmail.com>
2026-09-01 18:15:06 +08:00
renovate[bot] 4031b31837 fix(deps): update module github.com/azure/azure-sdk-for-go/sdk/azcore to v1.23.1 (#2985)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-01 18:01:59 +08:00
renovate[bot] 9b34ca5bf1 fix(deps): update module github.com/coreos/go-oidc to v2.5.0+incompatible (#2711)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-01 17:59:51 +08:00
renovate[bot] 666b1a039d fix(deps): update module golang.org/x/crypto to v0.55.0 (#2993)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-01 17:57:45 +08:00
hugcabbage 8f9a09d359 fix(drivers/guangyapan): report multipart upload progress to copy task (#2989)
multipartUploadToOSS passed the UpdateProgress callback into
stream.NewStreamSectionReader, which ignores the up argument, so the
callback was never invoked while uploading parts. As a result,
cross-storage copy tasks targeting GuangYaPan stayed at 0% and showed no
progress bar or speed in the task list.

Fix by tracking the uploaded byte count and invoking up after every
part is uploaded, keeping consistent with other drivers' upload flow.

Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-09-01 17:22:50 +08:00
renovate[bot] 394bb8f80e chore(deps): update go toolchain directive to v1.26.5 (#2733)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-30 17:25:38 +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
renovate[bot] ff3cb8b931 chore(deps): update actions/setup-go action to v7 (#2798)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-16 19:50:52 +08:00
Seven 7aea393a6d fix(drivers/115_open): populate file size when resolving paths (#2797)
* fix(115_open): populate file size when resolving paths

* feat(drivers/115_open): update 115-sdk-go
2026-07-16 19:46:15 +08:00
renovate[bot] 36168c86a0 fix(deps): update module github.com/rclone/rclone to v1.74.4 (#2744)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-16 15:53:43 +08:00
Shelton Zhu 24332e371f fix(115,115share): update github.com/SheltonZhu/115driver to v1.3.4 (#2794)
fix(115,115share): support empty User-Agent for UA-free CDN download links

Fixes #SheltonZhu/115driver/issues/80
2026-07-16 09:49:29 +08:00
renovate[bot] 6b702afc0f fix(deps): update module gorm.io/gorm to v1.31.2 (#2758)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-16 00:50:53 +08:00
renovate[bot] 78db0f7aff chore(deps): update docker/setup-qemu-action action to v4 (#2765)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-16 00:35:50 +08:00
renovate[bot] e469693114 fix(deps): update module github.com/bodgit/sevenzip to v1.6.5 (#2789)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-16 00:35:28 +08:00
renovate[bot] 5961289b83 fix(deps): update module github.com/nwaples/rardecode/v2 to v2.2.5 (#2699)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-16 00:29:25 +08:00
renovate[bot] 0527dc41af fix(deps): update module github.com/deckarep/golang-set/v2 to v2.9.0 (#2712)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-16 00:24:18 +08:00
renovate[bot] b1d298d192 fix(deps): update module github.com/go-resty/resty/v2 to v2.17.2 (#2718)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-16 00:20:11 +08:00
renovate[bot] 651b5cea1c fix(deps): update module github.com/protonmail/gopenpgp/v2 to v2.10.0 (#2742)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-16 00:11:32 +08:00
renovate[bot] 5aeaf7a8c8 fix(deps): update module github.com/shirou/gopsutil/v4 to v4.26.6 (#2745)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-16 00:08:16 +08:00
ShenLin 651da18da4 fix(handles): add src_name validation in FsBatchRename
- Validate source names with checkRelativePath before batch renames
- Reject invalid source paths with a forbidden response

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2026-07-15 16:11:57 +08:00
MadDogOwner 5a5d8d6e0e refactor(drivers/github_releases): remove internal caching and add pagination support (#2775)
* refactor(github_releases): remove internal caching, use global cache instead

- Remove Release/Releases/OtherFile cache fields from MountPoint struct
- Convert instance methods to pure functions (releaseToFiles, releasesToVersionDirs, etc.)
- Make List() fetch fresh data from GitHub API on every call
- Add githubGet helper to centralize GitHub API requests
- Remove unused GetRequest method and IsAncestorDir function

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

* feat(github_releases): add pagination and max page limit for all versions

- Add PerPage config to control releases per page (default 30, max 100)
- Add MaxPage config to limit max pages fetched (0 = unlimited)
- Rewrite getAllReleases to support automatic pagination

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

* chore(github_releases): move utils from driver.go to util.go

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

* chore(github_releases): revert changes to GetRequest

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

* chore(github_releases): use more common format for github proxy url

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

* fix(github_releases): show_readme in empty releases case

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

* fix(github_releases): preserve README and LICENSE name variants

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: GitHub Copilot <copilot@github.com>
2026-07-15 14:19:56 +08:00
renovate[bot] 061c1e2e1e chore(deps): update docker/setup-buildx-action action to v4 (#2764)
[no ci]
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-14 14:30:49 +08:00
renovate[bot] caed356200 chore(deps): update docker/metadata-action action to v6 (#2763)
[no ci]
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-14 14:30:24 +08:00
renovate[bot] 74af297471 chore(deps): update docker/login-action action to v4 (#2762)
[no ci]
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-14 14:29:43 +08:00
renovate[bot] 7c54b0e3e4 chore(deps): update docker/build-push-action action to v7 (#2761)
[no ci]
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-14 14:29:10 +08:00
renovate[bot] a632356902 chore(deps): update benjlevesque/short-sha action to v4 (#2760)
[no ci]
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-14 14:25:01 +08:00
renovate[bot] 82ea8d0d01 chore(deps): update actions/cache action to v6 (#2759)
[no ci]
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-14 14:18:52 +08:00
MadDogOwner eb48671202 fix(drivers/s3): custom user agent and method fixes (#2780)
* feat(drivers/s3): support custom ua

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

* fix(drivers/s3): add context to copy and remove file methods

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

* fix(drives/s3): avoid double-prepending root path

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: Copilot <copilot@github.com>
2026-07-11 11:46:09 +08:00
renovate[bot] f3e74fbdf1 fix(deps): update module github.com/quic-go/quic-go to v0.60.0 (#2743)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-10 12:24:49 +08:00
renovate[bot] e670322ee3 fix(deps): update module github.com/maruel/natural to v1.3.0 (#2739)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-10 12:24:49 +08:00
renovate[bot] 8930e1945e fix(deps): update module google.golang.org/grpc to v1.82.0 (#2754)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-10 12:24:49 +08:00
renovate[bot] daaba0d7ea fix(deps): update module gorm.io/driver/postgres to v1.6.0 (#2756)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-10 12:24:48 +08:00
renovate[bot] a81f54488f fix(deps): update module gorm.io/driver/sqlite to v1.6.0 (#2757)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-10 12:24:48 +08:00
ShenLin 59bd343140 fix(sharing): enforce base path boundaries
* 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>
2026-07-10 12:24:40 +08:00
renovate[bot] 757f9d383d fix(deps): update module github.com/dlclark/regexp2 to v1.12.0 (#2713)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-08 18:35:18 +08:00
renovate[bot] 7ded6dfe2c chore(config): migrate Renovate config (#2735) 2026-07-08 18:08:04 +08:00
New Future a283f2b52a feat(azure_blob): preserve content type and md5 (#2734) 2026-07-08 11:56:10 +08:00
MadDogOwner bb3bc31609 chore(workflows): upgrade actions (#2728)
upgrade actions cross all workflow files:

- actions/checkout@v6 -> actions/checkout@v7
- actions/cache@v4 -> actions/cache@v6
- actions/download-artifact@v4 -> actions/download-artifact@v8

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-07-06 21:41:25 +08:00
Unity_exe 744021d80d chore(wps/driver): remove CompanyID check (#2727)
Fixes #2543
2026-07-06 12:23:12 +08:00
renovate[bot] 94eac2e91e fix(deps): update github.com/t3rm1n4l/go-mega digest to 4de2f12 (#2710) 2026-07-02 07:56:08 +08:00
Yinan Qin a92d59d35c fix(build.sh): remove rm -rf .git/ (#2703)
Signed-off-by: elysia <a.elysia@proton.me>
2026-07-01 17:16:57 +08:00
Yinan Qin fcae009bd3 fix(workflow): using github-script (#2701)
* fix(workflow): using github-script

* fix more

Signed-off-by: Yinan Qin <elysia-best@simplelinux.cn.eu.org>

---------

Signed-off-by: Yinan Qin <elysia-best@simplelinux.cn.eu.org>
2026-07-01 16:45:15 +08:00
Pikachu Ren f63a5e15ee fix(deps): update module github.com/stangelandcl/ppmd v0.1.1 (#2698) 2026-07-01 16:00:18 +08:00
renovate[bot] d85980d3d9 fix(deps): update github.com/cloudsoda/go-smb2 digest to d8c5600 (#2298)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-01 15:41:25 +08:00
renovate[bot] c8306256ff chore(deps): update go toolchain directive to v1.26.4 (#2697)
* chore(deps): update go toolchain directive to v1.26.4

* chore(build.sh): update go version for loongarch abi1.0

Signed-off-by: Yinan Qin <elysia-best@simplelinux.cn.eu.org>

---------

Signed-off-by: Yinan Qin <elysia-best@simplelinux.cn.eu.org>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Yinan Qin <elysia-best@simplelinux.cn.eu.org>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-07-01 15:37:27 +08:00
renovate[bot] 5273a77854 fix(deps): update module github.com/gin-contrib/cors to v1.7.7 (#2688)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-01 15:36:47 +08:00
renovate[bot] cc3d8a06a7 fix(deps): update module github.com/bodgit/sevenzip to v1.6.4 (#2682)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-07-01 15:32:28 +08:00
renovate[bot] 925a2422d6 chore(deps): update github.com/openlistteam/reflink digest to 78760ea (#2693)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-07-01 15:29:04 +08:00
renovate[bot] 33015eee9f fix(deps): update module github.com/mholt/archives to v0.1.5 (#2690)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-01 15:28:42 +08:00
renovate[bot] 1be74776f6 fix(deps): update module github.com/ncw/swift/v2 to v2.0.5 (#2691)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-01 15:26:43 +08:00
renovate[bot] 31810f556c fix(deps): update module github.com/sirupsen/logrus to v1.9.4 (#2695)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-01 15:25:27 +08:00
renovate[bot] 30922b6d52 fix(deps): update module github.com/pkg/sftp to v1.13.10 (#2694)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-01 15:24:55 +08:00
renovate[bot] 759adfca21 fix(deps): update module github.com/charmbracelet/bubbles to v0.21.1 (#2686)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-01 13:15:58 +08:00
Pikachu Ren bfbc441fa6 fix(drivers/189pc): sync .torrent file when copy/move/rename/upload (#2522)
* fix(torrent): sync .torrent file when copy/move/rename/upload

* fix(torrent): prevent recursive torrent generation

* fix(189pc): address review comments on torrent sidecar handling

- Only append SHA-1 piece hash when n > 0, preventing spurious piece
  for empty files (BitTorrent v1 requires 0 pieces for 0-byte files)
- Explicitly guard torrent generation with size > 0
- Log findFileByName errors in torrentFollowCopy/Move/Rename instead of
  silently discarding them
- Log WaitBatchTask failure for follow-move operation
- Rename Cloud189File.ParentId to ParentID to match Go initialism
  conventions (consistent with Cloud189Folder.ParentID, Cloud189File.ID)

* revert(ci): go .sum 115 sdk

---------

Co-authored-by: Suyunmeng <Susus0175@proton.me>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-07-01 11:35:45 +08:00
Yinan Qin 866793f485 fix(go.mod): update Go version to 1.25 (#2692)
Signed-off-by: elysia <a.elysia@proton.me>
2026-07-01 11:21:06 +08:00
renovate[bot] 40b39000ab fix(deps): update github.com/t3rm1n4l/go-mega digest to 6845944 (#2088)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-01 10:01:24 +08:00
风月同天 6eedff851c feat(drivers): add Cloudflare Image Bed support (#2427)
* feat(driver): add Cloudflare Image Bed support

* fix: restore accidentally deleted file and name

* refactor: rename driver to cloudflare_imgbed and fix module structure

- Rename driver identifier and directory to 'cloudflare_imgbed' for consistency.
- Remove invalid 'replace' directive in go.mod.
- Restore accidentally modified/deleted files in public/dist.
- Update driver registration in drivers/all.go.

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

* fix: use base.NewRestyClient() and use e.g

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

* fix:go fmt

* feat(driver/cloudflare-imgbed): enhance cloudflare_imgbed API integration with improved error handling and pagination

* refactor

* feat(cloudflare_imgbed): implement upload functionality and optimize performance

- Added support for standard multipart form upload with zero-copy streaming.
- Implemented HuggingFace LFS direct upload for large files (>20MB).
- Integrated with OpenList global rate limiter and progress tracking.
- Optimized memory usage using io.MultiReader for request body construction.
- Added configurable upload threads for chunked HF uploads.
- Support auto mkdir dir when in upload

* refactor: simplify path handling logic

* refactor(cloudflare_imgbed): streamline API endpoint constants and improve initialization logic

* refactor(cloudflare_imgbed): clean up upload logic and remove unused functions

* docs: update help descriptions to English in cloudflare_imgbed

* feat(cloudflare_imgbed): add virtual directory support

* refactor(weak_cache): iImprove weak pointer cleanup handling

Store a cleanup handle alongside weak pointers and stop previous cleanups when overwriting entries to avoid stale removals and leaked cleanup handlers.

Ensure Delete signals success and stops associated cleanup. Add Clear to stop all active cleanups. Use entry identity in the cleanup callback to avoid removing newly inserted values.

* fix bug

* Apply suggestions from code review

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>

* Adds uploadFolder param and streams base64 sample

Adds an uploadFolder query parameter to forward the destination path to the backend. Replaces the fixed-size sample read with a streaming base64 encoder to avoid truncation and reduce allocations

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

* refactor: add context parameter to doRequest and related calls

* fix: update List method to check args.Refresh before virtual directory mask

* refactor: optimize List method and improve error handling in doRequest

* feat: add public URL support and multi-channel chunked upload

- Support multi-channel chunk size configurations (e.g., Telegram, CFR2, S3, Discord).
- Fix 401 unauthorized error when merging chunks in HuggingFace channel.

---------

Signed-off-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: j2rong4cn <j2rong@qq.com>
Co-authored-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-06-30 16:26:35 +08:00
renovate[bot] aea77c5967 fix(deps): update module github.com/aws/aws-sdk-go to v1.55.8 (#2574)
fix(deps): update aws-sdk-go monorepo to v1.55.8

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-30 16:23:41 +08:00
renovate[bot] 009d834e71 fix(deps): update module github.com/antchfx/htmlquery to v1.3.6 (#2601)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-06-30 16:23:04 +08:00
Yinan Qin e9ea991584 fix(clean_docker): only fetch up to 10 pages of image versions (#2680)
fix(clean_docker): only fetch upto 10 pages of image versions

Signed-off-by: Yinan Qin <elysia-best@simplelinux.cn.eu.org>
2026-06-30 15:00:46 +08:00
Pikachu Ren d4aa8b6a15 fix(driver): 123pan url www.123pan.com -> yun.123pan.com (#2678) 2026-06-30 10:36:17 +08:00
Yinan Qin 9e55a0111b feat(actions): add workflow to clean up untagged Docker images (#2657)
* feat(actions): add workflow to clean up untagged Docker images

Signed-off-by: elysia <a.elysia@proton.me>

* fix(actions): suggestions from codex

Signed-off-by: elysia <a.elysia@proton.me>

* chore: remove cron task

---------

Signed-off-by: elysia <a.elysia@proton.me>
2026-06-29 18:48:15 +08:00
ShenLin f869afc71f docs(contributing): define policy for fully automated contributions (#2655)
* docs(contributing): define policy for fully automated contributions

- 在贡献指南中定义完全自动化贡献及账号判定因素
- 在贡献指南中要求 PR 描述遵循仓库 PR 模板
- 在代理指引中补充维护者处理完全自动化贡献的政策

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

* docs(contributing): apply suggestions from @PIKACHUIM

Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
Signed-off-by: ShenLin <773933146@qq.com>

* docs(contributing): apply suggestions from @PIKACHUIM

Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
Signed-off-by: ShenLin <773933146@qq.com>

---------

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Signed-off-by: ShenLin <773933146@qq.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-06-25 10:37:05 +08:00
MadDogOwner e960035b65 refactor(drivers/139): adapt new capacity calculation (#2651)
refactor: 合并个人和家庭磁盘信息请求为统一的配额详情请求

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-06-25 00:44:15 +08:00
ShenLin a0f001c168 fix(drivers/chunk): handle missing chunk part zero (#2619)
* fix(chunk): handle missing chunk part zero

- Return ObjectNotFound when chunk directory lacks part 0
- Ignore invalid negative part indexes while scanning chunks

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

* fix(chunk): handle missing all file chunk

* .

* fix(chunk): handle incomplete file chunks

---------

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>
2026-06-25 00:37:04 +08:00
ShenLin c8e7f35761 docs(readme): expand localized readmes (#2645)
* docs(readme): expand localized readmes

- Move existing non-English README files into the README directory.
- Add Korean, German, Russian, French, Spanish, and Arabic README variants.
- Update README language links and UrlTree sample URL for the new path.

* docs(readme): update localized storage links

- 将韩文 README 文件名从 kr 调整为 ko
- 为新增本地化 README 展开存储列表链接
- 补充 DingTalk Docs 存储条目并同步语言导航

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

---------

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-06-24 19:09:45 +08:00
Ovear 6ed7db1ee7 fix(drivers/189pc): pass pointer to RenameResp in Rename method (#2647)
Rename function passed RenameResp by value instead of pointer, causing
the API response to be discarded and producing a zero-value file entry
with empty name, zero size, and zero timestamps after rename.
2026-06-23 15:26:46 +08:00
ucscynsqfhnlmntznkaeporoc 5a12c8d2ba fix(ilanzou): fix redirect (#2649) 2026-06-23 10:51:46 +08:00
tide-wait b86d10fa2f fix(drivers/115_open): simplify Move and Copy methods to return error directly (#2505) 2026-06-22 18:07:23 +08:00
Unity_exe aa534a955b feat(drivers/alidoc): add DingTalk Docs driver (#2543)
* feat(drivers/alidoc): add DingTalk Docs driver

Generated with OpenAI Codex

* chore(drivers/alidoc): update metadata copy

Generated with OpenAI Codex

* chore(drivers/alidoc): update read-only alert copy

Generated with OpenAI Codex

* chore(gitignore): remove alidoc ignore rule

Generated with OpenAI Codex

* feat(alidoc): support upload move and recycle delete

Generated with OpenAI Codex

* fix(alidoc): commit uploaded files after oss transfer

Generated with OpenAI Codex

* feat(alidoc): support mkdir copy and rename

Generated with OpenAI Codex

* chore(alidoc): remove unused readonly helper

* chore(alidoc): remove driver alert copy

* refactor(alidoc): simplify id-based driver behavior

Generated with OpenAI Codex

* refactor(alidoc): stream multipart uploads directly

Generated with OpenAI Codex

* refactor(alidoc): use retry helper for multipart uploads

Generated with OpenAI Codex

* Update drivers/alidoc/driver.go

Co-authored-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
Signed-off-by: Unity_exe <zjhcx12@gmail.com>

* refactor(alidoc): simplify write operation responses

Generated with OpenAI Codex

* fix(alidoc): update multipart upload progress

Generated with OpenAI Codex

* docs(readme): sync DingTalk Docs support across translations

* refactor(alidoc): simplify file operations and remove redundant checks

* fix(wps): update login state handling and improve error messages

* fix(alidoc): validate cookie with mine info endpoint

Generated with OpenAI Codex

* fix(alidoc): skip root folder listing during init

---------

Signed-off-by: Unity_exe <zjhcx12@gmail.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Co-authored-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
Co-authored-by: j2rong4cn <j2rong@qq.com>
2026-06-22 14:40:59 +08:00
yunxuan d403f75da2 fix: prevent panic in unaligned 64-bit atomic (#2637)
* fix(net): prevent panic in unaligned 64-bit atomic on ARMv7

Convert int64 fields written and readingID to atomic.Int64
guarantees 8-byte alignment on 32-bit ARM architectures.

Unaligned 64-bit atomics fault with SIGILL on armv5/armv6
and armv7. Fixes file copy operations.

* fix(atomic): migrate more atomic useage

* fix(alias): improve link handling and add Clone method for Link struct

* fix warn

* fix(mem): simplify memory reservation handling in MemoryGrowCheck

* fix(link): simplify link handling by using Clone method

* fix bug

* fix(hash): typo

Signed-off-by: Yinan Qin <a.elysia@proton.me>

---------

Signed-off-by: Yinan Qin <a.elysia@proton.me>
Co-authored-by: Elysia <a.elysia@proton.me>
Co-authored-by: j2rong4cn <j2rong@qq.com>
2026-06-22 14:37:44 +08:00
Sorubedo 3abdf7990b fix(drivers/ftp): add cwd_list option and filter path-separated entries (#2621)
1. Add `cwd_list` option to switch LIST command logic
   Use CWD + LIST "" instead of LIST <path> to fix garbled non-UTF8 paths on legacy Chinese FTP servers, eliminate fake duplicate folders.
2. Filter entries with "/" in filename
   Skip cdir marker entries carrying full path names, compliant with FTP filename specification.

Co-authored-by: Claude <81847+claude@users.noreply.github.com>
2026-06-19 22:44:30 +08:00
ShenLin 3b017c2b5c feat(mcp): add mcp endpoint for whole openlist (#2485)
* feat(mcp): add initial MCP tools support

- 新增 MCP 路由与 session 初始化流程
- 接入 tools/list 与 tools/call,并开放 openlist.fs.list
- 补充 MCP 相关协议与路由测试

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

* refactor(mcp): move MCP implementation into server/mcp

- 将 MCP 实现与测试迁移到 server/mcp 目录
- 保留 server/mcp.go 作为路由接入包装入口
- 对齐 webdav、s3、ftp、sftp 的目录组织风格

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

* fix(mcp): address endpoint review issues

- 收紧 Streamable HTTP Accept 头校验
- 为 MCP session 增加过期清理和数量上限
- 简化 fs.list 参数解析并修复分页边界
- 使用独立 Server 实例隔离 MCP 测试状态

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

* feat(mcp): add fs get and link tools

- 新增 openlist.fs.get 和 openlist.fs.link 工具
- 复用文件详情、代理链接和权限校验逻辑
- 补充工具列表和参数解析测试

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

* fix(mcp): improve protocol negotiation and proxy handling

- Remove WebDAV proxy URL policy from MCP proxy link detection
- Return server protocol version during initialize negotiation
- Return JSON-RPC error body for invalid MCP Accept header
- Add tests for MCP proxy and HTTP negotiation behavior

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

* fix(mcp): set Allow header for GET requests

- 为 MCP GET 405 响应添加 Allow 头
- 补充 GET 405 响应头断言

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

* refactor(mcp): use mutex for session store

- 将 MCP session 锁改为 Mutex
- 让锁类型匹配会更新 lastUsedAt 的访问路径

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

* fix(mcp): negotiate initialize protocol version

- 添加 MCP 协议版本协商函数
- 不支持客户端版本时返回服务端支持版本

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

* revert(mcp): drop protocol version negotiation wrapper

- 撤回 MCP 协议版本协商包装函数
- 恢复 initialize 直接返回服务端协议版本

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

* fix(mcp): limit and reuse sessions

- 将 MCP 全局 session 上限调整为 128
- 添加单用户 16 个 session 上限
- initialize 复用同用户已有 session 标识
- 补充 session 复用和上限裁剪测试

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

* fix(mcp): require path for fs list

- 拒绝 openlist.fs.list 的空参数和 null 参数
- 校验 fs.list 缺失 path 时返回 -32602
- 添加 fs.list 参数解析测试覆盖错误文案

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

* fix(mcp): enforce protocol version header

- 校验非 initialize 请求的 MCP-Protocol-Version 头
- 拒绝缺失或不支持协议版本的后续 POST 请求
- 添加协议版本头缺失和不匹配测试

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

* test(mcp): serialize setting cache mutation

- 为修改全局设置缓存的测试添加包级互斥锁
- 保留 ClearAll 清理逻辑,避免并发测试互相影响

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

* feat(mcp): add config switch

- Add MCP config section with disabled default
- Register MCP routes only when enabled

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

* fix(mcp): handle missing session explicitly

- 区分缺失 MCP session 与未知 MCP session
- 为未知 session 返回 not found 错误
- 添加 MCP session 错误处理测试

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

* feat(mcp): support latest protocol negotiation

- Upgrade default MCP protocol version to 2025-11-25
- Preserve 2025-06-18 compatibility through initialize negotiation
- Validate subsequent request protocol version against the negotiated session version
- Add tests for latest and older protocol negotiation paths

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

* fix(mcp): relax streamable http compatibility

- 允许缺失协议版本头时使用会话协商版本
- 放宽 Accept 头兼容 JSON、SSE 和通配类型
- 补充 MCP 初始化和协议版本兼容性测试

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

---------

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-06-19 00:32:00 +08:00
MadDogOwner a42e367660 fix(drivers/github_releases): skip broken repos instead of returning 500 (#2494)
* fix(drivers/github_releases): skip broken repos instead of returning 500

When multiple repos are configured and one fails (404, rate limit, etc.),
the driver now logs a warning and skips that repo instead of panicking
with a nil pointer dereference that caused a 500 error for the entire
storage. Added proper error propagation from GetRequest through
RequestRelease/RequestReleases/GetOtherFile, and nil checks on all
Release/Releases dereferences.

Instead of hiding broken repos entirely, still display them as directory
entries in parent listings. Return an error only when the user navigates
into a broken repo.

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Mimo <208276378+mimo@users.noreply.github.com>

* fix(drivers/github_releases): apply patches

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Mimo <208276378+mimo@users.noreply.github.com>
Co-authored-by: GitHub Copilot <copilot@github.com>
2026-06-19 00:12:18 +08:00
Castronaut f45473357e fix(drivers/webdav): normalize missing path error (#2611)
Normalize WebDAV 404 responses from `Stat` to `errs.ObjectNotFound`.

This fixes the mkdir pre-check path: when the target folder does not exist, `op.MakeDir` can now treat the lookup as a normal missing object and continue to issue `MKCOL` through the WebDAV driver.

Co-authored-by: ChatGPT <noreply@openai.com>
2026-06-19 00:11:38 +08:00
EzraRT dcfefce85d fix(webauthn): enable discoverable keys (#2451)
Set `WithResidentKeyRequirement` option during registration to enable discoverable keys.
Existing keys do not require migration. They won't appear without entering username, but work normally after username input, legacy flows remain unaffected.
2026-06-19 00:04:25 +08:00
ShenLin d349765617 fix(drivers/thunder): handle missing token errors (#2623) 2026-06-18 23:17:24 +08:00
ShenLin ace7482bc2 fix(offline-download): block cloud metadata endpoints (#2487) 2026-06-18 23:16:16 +08:00
ShenLin eadf03a4f8 fix(upload): respect overwrite for direct uploads (#2625)
* fix(upload): respect overwrite for direct uploads

- 将 Direct Upload 的 overwrite 参数传递到后端检查逻辑
- 覆盖上传时允许已存在目标继续生成直传信息
- 非覆盖上传时按完整目标路径返回 file exists

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

* fix(upload): validate direct upload target checks

- 校验直传文件名只能是单个路径段
- 在非覆盖直传检查中返回非 object not found 错误
- 在底层直传信息生成前保留真实探测错误

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

* fix(upload): preserve direct upload conflict status

- 将非覆盖直传的并发已存在错误返回为 403
- 保持直传存在性检查的前端错误文案不暴露路径

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

---------

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-06-16 14:45:43 +08:00
hcrgm da84a800ab feat(baidu): support link cache lasting one hour (#2033) 2026-06-16 13:49:24 +08:00
ShenLin b05a51a062 feat(archive): support livp as zip archive (#2624)
fix(archive): support livp as zip archive

- 将 .livp 注册为 ZIP 压缩包识别格式
- 复用现有 ZIP 解析逻辑支持 LIVP 预览和解压
- 补充 .livp 扩展名注册测试

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-06-16 13:46:17 +08:00
ShenLin ffe3f3cfa3 fix(local): remove thumbnail cache on delete (#2627)
- 复用本地缩略图缓存路径生成逻辑
- 删除本地文件成功后清理对应缩略图缓存
- 增加本地文件删除缓存清理测试

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-06-16 13:45:15 +08:00
ShenLin 7e55f11e4a fix(index/meilisearch): refresh progress after update (#2628)
fix(index): refresh progress after update

- 手动更新索引完成后刷新索引进度状态
- 保留现有对象计数避免引入计数差值风险
- 记录更新失败时的错误信息

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-06-16 13:43:43 +08:00
ShenLin e7bccc636a docs(agents): add agent workflow instructions (#2629)
- 添加 PR 创建前读取模板的 agent 规则
- 添加提交消息格式和签名相关规则
- 明确不得编造测试、验证或提交内容

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-06-16 13:42:31 +08:00
ShenLin b7f9e8ef0a fix(sftp): add connection timeout (#2626)
- 为 SFTP SSH 连接设置启动超时
- 避免远端不可达时长时间阻塞存储初始化

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-06-16 13:40:57 +08:00
So d7c332ca13 fix(s3): only skip direct redirect for true sub-resource queries (#2604) 2026-06-12 17:46:51 +08:00
Pikachu Ren 64d39114ee chore(doc): add sponsors (#2531) 2026-06-12 12:38:49 +08:00
So 88d256de73 feat(s3): support direct transfer redirects (#2598)
Redirect S3 GET object requests to direct links when the underlying storage can provide one and proxying is not required.

Redirect eligible S3 PUT object requests to HttpDirect single PUT upload URLs with 307, while falling back to the existing gofakes3 stream path for unsupported uploads.

Allow OneDrive Sharelink direct upload info to use simple content PUT URLs for files within Microsoft's single-upload limit.

Co-authored-by: syscc <syscc@users.noreply.github.com>
Co-authored-by: Codex <codex@openai.com>
2026-06-12 08:59:34 +08:00
Yinan Qin 5a92dc2834 chore(workflows): update workflow deps and rm 3rd-party actions (#2600)
Signed-off-by: Elysia <a.elysia@proton.me>
2026-06-12 01:03:44 +08:00
So 726bbf4bd2 fix(115-open): map SDK not found errors (#2596) 2026-06-11 18:46:44 +08:00
Sai Asish Y bd6cf5bc1e fix(teldrive): avoid index out of range panic when listing an empty dir (#2585) 2026-06-11 18:40:26 +08:00
So 089315118d feat(onedrive_sharelink): support upload and folder sizes (#2595)
Co-authored-by: syscc <syscc@users.noreply.github.com>
Co-authored-by: OpenAI Codex <codex@openai.com>
2026-06-10 16:43:26 +08:00
So 9737006a8d feat(onedrive_sharelink): support direct download redirects (#2591)
fix(onedrive_sharelink): support direct download redirects

Resolve SharePoint item metadata to obtain @content.downloadUrl for redirect downloads.

Co-authored-by: syscc <syscc@users.noreply.github.com>
Co-authored-by: Codex <codex@openai.com>
2026-06-08 11:39:11 +08:00
j2rong4cn 054db9f5eb fix(op): use oldName variable for cache updates in Rename function (#2570) 2026-06-03 19:56:55 +08:00
Jealous 9b587ee165 fix(archive): prefer utf-8 for non-EFS zip names (#2557) 2026-06-01 01:50:47 +08:00
j2rong4cn 9282e8ef09 fix(cache,mem): replace finalizers with runtime.AddCleanup (#2535) 2026-06-01 01:50:20 +08:00
Akizon ac80fe19bf feat(drivers): add emby driver (#2270)
* feat: add emby driver support with stream and download link methods

* refactor: organize codes into separate files

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

* fix: resolve fileID

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2026-05-31 14:54:34 +08:00
yuxiaoyu8192 cd6643a642 fix(chaoxing): support multiple uploadDate formats (#2545)
* Update types.go

Signed-off-by: yuxiaoyu8192 <103018181+yuxiaoyu8192@users.noreply.github.com>

* Update types.go

代码格式化

Signed-off-by: yuxiaoyu8192 <103018181+yuxiaoyu8192@users.noreply.github.com>

* Update types.go

时间解析失败返回空

Signed-off-by: yuxiaoyu8192 <103018181+yuxiaoyu8192@users.noreply.github.com>

---------

Signed-off-by: yuxiaoyu8192 <103018181+yuxiaoyu8192@users.noreply.github.com>
2026-05-31 14:54:20 +08:00
Pikachu Ren ba6f96ca4e fix(driver): json: cannot unmarshal number into Go struct field RenameResp.id of type string (#2526) 2026-05-30 10:36:37 +08:00
Suyunjing 9cc5dd969b fix(offline_download): block SimpleHttp temp file path traversal via strict filename sanitization
* fix(offline_download): prevent path traversal

* fix(SimpleHttp): improve filename validation

* fix(offline_download): harden SimpleHttp filename and temp path checks

* simplify filename validation

---------

Co-authored-by: ILoveScratch2 <ilovescratch@foxmail.com>
Co-authored-by: j2rong4cn <j2rong@qq.com>
2026-05-27 17:18:31 +08:00
Suyunjing 98c32d3be4 fix(doubao_new): remove temp file after cross-storage put (#2530) 2026-05-27 16:49:26 +08:00
Suyunjing 4c77b9c7bf fix(fs): clear skipped names before copy and move tasks (#2520) 2026-05-27 13:26:16 +08:00
Suyunjing 3b1760e959 fix(offline_download): restore SimpleHttp fallback for http links (#2516)
- Fixed a regression where SimpleHttp returned the same unsupported scheme error for normal HTTP and HTTPS links.
2026-05-26 13:11:21 +08:00
Pikachu Ren b28208bd76 fix(189pc): handle numeric res_code in RenameResp to fix JSON unmarshal error (#2489) 2026-05-25 22:13:44 +08:00
Shelton Zhu ffbbc1ccdf fix(115): fix capacity display and CDN 403 errors (#2510)
- Fix #2343: update 115driver to v1.3.3 to handle float size values
- Fix #2349, #2356, #2502: use base.UserAgent as fallback when User-Agent header is empty

The 115 CDN returns 403 "no cookie value" when the User-Agent header
is empty or doesn't match the cookie. This fix ensures a consistent
browser User-Agent is used for download link generation.
2026-05-25 22:10:53 +08:00
Pikachu Ren 1d071c0fd8 feat(func): support ed2k & magnet & torrent offline download (#2452)
Add end-to-end offline download support for torrent files, magnet links, and ed2k links, including torrent parse and generate APIs, CAS-based rapid upload for Cloud189, and protocol-aware tool routing with transfer flow improvements.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
Co-authored-by: j2rong4cn <j2rong@qq.com>
Co-authored-by: Suyunjing <suyunmeng@oplist.org.cn>
2026-05-25 14:34:21 +08:00
ShenLin 948e87159d docs(community): update contribution guidelines and templates (#2507)
优化 PR 模板结构和检查项
增加 PR 中 AI 辅助披露说明和工具范围
在 Issue 模板中增加 AI 辅助内容字段
补充贡献指南中的社区政策和 AI 披露要求
将 Go 版本要求改为以 go.mod 声明为准
修正文档链接和行为准则格式细节
2026-05-25 12:13:22 +08:00
ShenLin c3df8da577 chore(README): fix-sites (#2501)
* Squashed commit of the following:

commit f029df88e4ebc36e0886662193dc99f8276959ce
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 14:00:36 2025 +0800

    Add Terms of Use and Privacy Policy links to READMEs

    Added links to the Terms of Use and Privacy Policy in the English, Chinese, Japanese, and Dutch README files to provide users with easy access to legal information.

commit 00f825d9e2
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 13:53:29 2025 +0800

    Update documentation links in README files

    Replaced plain documentation URLs with labeled links and icons in English, Chinese, Japanese, and Dutch README files for improved clarity and user experience.

commit 732dcfa5b1
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 13:40:52 2025 +0800

    fix format

commit e2ad8eabb8
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 13:38:28 2025 +0800

    Revert "test large name"

    This reverts commit affedc845b.

commit affedc845b
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 13:37:43 2025 +0800

    test large name

commit 382cd6425f
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 13:34:42 2025 +0800

    Add Dutch README and update language links

    Added a new Dutch translation (README_nl.md) and updated language navigation links in the English, Chinese, and Japanese README files to include Dutch.

commit e880acb71d
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 13:29:51 2025 +0800

    Add AGPL-3.0 license links to README files

    Updated the English, Chinese, and Japanese README files to include direct links to the AGPL-3.0 license text and the LICENSE file for clarity and easier access.

commit a0d1eadf3e
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 13:25:52 2025 +0800

    Move language and links sections below logo in READMEs

    Repositioned the language selection and related links sections to appear after the logo and separator in README.md, README_cn.md, and README_ja.md for improved layout consistency.

commit 70a0a32b7b
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 13:23:36 2025 +0800

    Revise and unify README files across languages

    Updated README.md, README_cn.md, and README_ja.md to improve structure, add navigation links, clarify project purpose, and unify feature lists. Enhanced formatting, added acknowledgments to original authors, and improved legal/disclaimer sections for consistency across English, Chinese, and Japanese documentation.

commit 2f32120908
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 12:56:26 2025 +0800

    Update Go Report Card badge URL in README

    Changed the Go Report Card badge to reference v3 instead of v4. This ensures the badge displays the correct status for the intended version.

commit 0fdfa2b365
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 12:53:43 2025 +0800

    Update README.md

commit 82713611c0
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 12:53:22 2025 +0800

    Update Go Report Card badge URL in README

    Changed the Go Report Card badge link to remove the '/v3' suffix, ensuring it points to the correct repository path.

commit 41acb3e865
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 12:52:46 2025 +0800

    Update project description in README

    Revised the introductory paragraph to emphasize OpenList's resilience and community-driven nature as a fork of AList, highlighting its commitment to defending open source against trust-based attacks.

commit 77aca6609a
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 12:50:45 2025 +0800

    Update README.md

commit 63a597f802
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 12:49:57 2025 +0800

    Improve README badge formatting and alignment

    Reformatted the badge section in the README for better readability and visual alignment. Updated the div to use 'align="center"' and placed each badge on its own line with proper indentation.

commit fcf7530dd8
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 12:46:38 2025 +0800

    Update logo size and remove migration note in README

    Set explicit width and height for the logo image and removed the note about migration progress, reflecting project updates.

commit 5f0645ded8
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 12:45:04 2025 +0800

    Revert README header to HTML

    Replaces markdown-based center alignment and badge/image syntax with HTML tags for better visual formatting and consistency in the README header.

commit 0f7ba9599d
Author: jyxjjj <773933146@qq.com>
Date:   Tue Jul 1 12:42:59 2025 +0800

    Revise README formatting and update project info

    Refactored the README to use markdown badge/link syntax, improved formatting, and clarified the disclaimer section. Updated Docker Deploy status, added a Contact Us section, and reordered the Contributors section for better project transparency and communication.

* chore(readme): fix sites

* chore(readme): fix sites
2026-05-24 09:49:07 +08:00
Yinan Qin 7cfb25558f fix(drivers/local): capture ENOTTY in reflink to allow fallback (#2492) 2026-05-21 15:52:11 +08:00
Chisiung 31b41f99f8 fix(offline_download): fix login failure caused by qBittorrent 5.2.0 returning HTTP 204 No Content on successful authentication (#2476) 2026-05-18 15:12:15 +08:00
j2rong4cn 9eae62581a refactor(cache)!: extract hybrid_cache package (#2477)
* refactor(HybridCache)!: extract hybrid_cache package and rename cache_threshold to auto_memory_limit

* split HybridCache and stores into internal/hybrid_cache package
* introduce BackingStore abstraction with BufferStore and FileStore
* rename CacheThreshold to AutoMemoryLimit in config/env/bootstrap
* update stream/request integration and related tests

* rename singleFileCache and MultiFileCache to singleFileStore and MultiFileStore

* refactor(HybridCache): improve memory management strategies in NewHybridCache

* rename

* alias hybrid_cache to hcache

* omments
2026-05-18 15:11:39 +08:00
Copilot daad21ef91 fix(driver/139): remove RFC-incompatible request header (#2478)
fix(139): remove RFC8441-incompatible Connection header

Agent-Logs-Url: https://github.com/OpenListTeam/OpenList/sessions/1c6b226d-02c4-4b43-80ad-5ab2861d30c3

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
2026-05-17 22:31:41 +08:00
j2rong4cn 219564b56c refactor(func): replace GinWithValue with GinAppendValues (#2475) 2026-05-15 17:59:53 +08:00
j2rong4cn ea19bed247 fix(setting): handle delete of setting item with empty key (#2131) 2026-05-14 23:23:44 +08:00
j2rong4cn b6db83ed5e refactor: unify stream caching via HybridCache (#2460)
* add LinearMemory

* replace mmap with LinearMemory

* remove unused code

* add GuardedMemory; add `min_free_memoryMB` conf

* add HybridCache and StreamBuffer

* log

* rename SizedReadWriterAt to Section

* 重构 FileStream,改用 HybridCache

* 重构 HybridCache,更新方法名并添加回滚功能;优化请求和流处理逻辑

* 重构 StreamSectionReader 接口,使用HybridCache

* 在 NewGuardedMemory 函数中添加了对 LinearMemory 的最终化处理,以确保内存释放

* .

* 优化检查逻辑

* 重命名

* 改进、重命名

* 修复

* 添加测试

* 移除HybridCacheReader并引入DynamicReadAtSeeker

* 重构缓存读取逻辑,简化代码并引入ReadFromN方法

* 优化缓存配置注释并修复下载器部分大小限制逻辑

* 优化中断逻辑

* 优化下载器代码

* 修复bug

* HybridCache添加多文件缓存模式

* 优化下载器并发,添加测试

* 修复bug

* 重命名+注释

* .

* fix(net): always cleanup downloader on interrupt

* fix(net): guard chunk enqueue with context cancel

* fix(net): update interrupt logic and add download interrupt test

* fix(test): update concurrency limit in high concurrency test

* refactor(buffer): simplify ReadAt logic

* refactor(config): update memory configuration logic

* .

---------

Co-authored-by: Suyunmeng <Susus0175@proton.me>
2026-05-14 22:14:54 +08:00
LuckyPhoenix 0726d16632 feat(189pc): implement AccessToken login (#2245)
Optimize the 189pc driver to implement AccessToken login
2026-05-12 23:08:02 +08:00
Pikachu Ren 7feec2b7d9 fix(driver): fix 189 & 189pc fastcopy form local storage (#2471)
* fix(driver): fix 189 & 189pc fastcopy form local storage

* fix(driver): fix 189 & 189pc fastcopy form local storage

* fix(driver): fix 189 & 189pc fastcopy form local storage
2026-05-12 21:45:06 +08:00
j2rong4cn c7c0cfaeb7 fix(fsmanage): improve path validation (#2437)
* fix(fsmanage): improve path validation in FsMove, FsCopy, and FsRemove functions
2026-05-06 11:58:00 +08:00
j2rong4cn d3a6b06566 perf: replace strings.Split with strings.SplitSeq (#2441) 2026-05-04 13:05:07 +08:00
mkitsdts e87e028a49 fix(internal/fs): add ObjectAlreadyExists error check (#2019)
* fix(webdav/drivers):add errors check

* chore(pkg/error):add errs.IsObjectAlreadyExists function

* chore(pkg/error):rollback error change

* chore(op/makedir):add IsObjectAlreadyExists check

* fix(driver/quark_uc):add makedir response checking

* fix(op/put):add makedir error checking

* chore(op/put):fix logic error

* fix(driver/uc):fix error resp check

* chore(op/makedir):add parentPath check

* fix(op/makedir):fix some errors

* fix(op/makedir):fix logic error

* fix(drivers/cloudreve_v4): add object existence error

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2026-05-03 19:10:31 +08:00
airium bfda719e64 fix(qbittorrent): handle non-200 response during login to prevent long startup waits (#2248) 2026-05-03 19:08:33 +08:00
Miao Zhao 7e37c40516 feat(sharing): allow custom share IDs (#2353)
feat: allow custom share IDs

   - Change sharing ID column from char(12) to varchar(64)
   - Add new_id field to UpdateSharingReq for renaming share IDs
   - Add ID validation (max 64 chars, alphanumeric/CJK/hyphens/underscores)
   - Add conflict check when updating share ID
   - Add customize_share_id permission (bit 15)

   Closes OpenListTeam/OpenList#1806
2026-05-03 11:06:28 +08:00
ZRHan e28406fa2c feat(webdav): implement Getter interface (#2421)
* feat(webdav): implement Getter interface

* fix(webdav): update Get method to use correct path handling

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

* fix(s3): correct path handling in Get method for object retrieval

---------

Co-authored-by: j2rong4cn <j2rong@qq.com>
Co-authored-by: Copilot <copilot@github.com>
2026-04-30 14:03:24 +08:00
ZRHan 9033b5502d feat(s3): implement Getter interface (#1790)
* feat(s3): implement Getter interface

* update path

* rm root
2026-04-29 13:51:06 +08:00
Seven 07506b003e feat(115_open): implement Getter interface (#1811)
* feat(115_open): implement Getter interface

* chore(115_open): get parentPath move to init
2026-04-29 13:50:41 +08:00
ShenLin 201a206ed9 fix(about): fix large logo on about page (#2418)
fix(about): fix large logo on about page via OpenList-Frontend#463
2026-04-28 23:54:41 +08:00
MadDogOwner 2d2d9ae213 fix(drivers/wps): correct account relevant handling (#2415)
* fix(drivers/wps): correct account modes handling

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

* feat(drivers/wps): enhance GetDetails for business account

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: Copilot <copilot@github.com>
2026-04-27 22:19:03 +08:00
MadDogOwner 376638978a fix(drivers/wps): implement driver.GetRooter interface (#2414)
* fix(drivers/wps): implement driver.GetRooter interface

* fix(drivers/wps): add User-Agent and Referer headers in Link method

* fix(drivers/wps): removing NoOverwriteUpload field

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-04-27 21:13:44 +08:00
MadDogOwner 29ec90e8e8 refactor(drivers/wps): remove resolveCache (#2411)
* refactor(drivers/wps): remove resolveCache

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

* fix(drivers/wps): add a small helper that unwraps model.ObjUnwrap

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

* fix(drivers/wps): correct misspell

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: Copilot <copilot@github.com>
2026-04-27 17:33:05 +08:00
MadDogOwner ece1518eac fix(drivers): add headers in Link methods (#2401)
* fix(drivers): add headers in Link methods

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-04-26 15:17:40 +08:00
MadDogOwner a5ba6a0e9d refactor(settings)!: move FilterReadMeScripts to frontend (#2346)
* refactor(settings)!: move FilterReadMeScripts to frontend

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

* chore: run go mod tidy

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-04-20 18:05:15 +08:00
MadDogOwner 331f575c17 fix(drivers/139): check cdnSwitch before returning cdnUrl in personalGetLink (#2379)
Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-04-19 09:54:17 +08:00
ShenLin b31ae9c9f6 ci(actions): upgrade actions/checkout to v6 (#2338)
Replace actions/checkout from v4 to v6 across workflows to prepare for the GitHub Actions Node.js 24 migration and avoid Node.js 20 deprecation risk.
2026-04-10 20:47:45 +08:00
Suyunjing 8d39d636be fix(build): lock musl outputs to fully static linking in build script and CI workflows (#2330) 2026-04-09 20:57:04 +08:00
Jealous da26e72bee fix(op): invalidate new path cache on meta path update (#2322) 2026-04-09 09:32:18 +08:00
MadDogOwner e11b8a82e7 fix(drivers/cloudreve_v4): remove token check for share (#2274)
Fixed the issue of token verification for shared links.
2026-04-04 18:43:08 +08:00
sdvcrx 12c9bdbd56 fix(offline_download): prevent infinite retry on status update failure (#2294) 2026-04-03 15:47:40 +08:00
Seven 9e49adc353 fix(drivers/openlist): pass through frontend refresh flag (#2307)
* fix(drivers/openlist): pass through frontend refresh flag
* fix(drivers/openlist): gate refresh flag forwarding by config
2026-04-03 15:41:25 +08:00
Pikachu Ren 9fdba3a730 feat(drivers/123_open): support 123 official app api (#2293)
* feat(driver): support 123 official app api

* fix(123_open): migrate api refresh to token.go

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

* fix(drivers/123_open): trigger proactive refresh with client credentials

* fix(drivers/123_open): use client-credential token endpoint for local refresh

Keep renewapi parsing for expires_in and map it to internal expiry time handling.

* fix(drivers/123_open): limit proactive refresh to client credentials

* fix(drivers/123_open): allow renewapi refresh token proactive init

* fix(drivers/123_open): update API address to use renewapi endpoint

* fix(drivers/123_open): simplify token refresh parsing

* fix(drivers/123_open): unify token expiration to expiredAt

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: Suyunmeng <Susus0175@proton.me>
Co-authored-by: Suyunjing <suyunmeng@oplist.org.cn>
2026-04-03 15:23:26 +08:00
Suyunjing 7bea29c18e refactor(db): migrate sqlite to pure-go and add mips compatibility switch (#2296)
- Switch default SQLite path to github.com/glebarez/sqlite to reduce CGO dependency pressure.
- Introduce a unified openSQLite entry in bootstrap and split driver selection by build tags.
- Add sqlite_cgo_compat fallback for linux mips, mips64, loong64 and mipsle to keep legacy target builds working.
- Update build.sh musl build flow to apply compatibility tag for mips-family targets.
- Update beta_release workflow to pass compatibility tag cleanly and avoid conflicting flag composition.
2026-04-03 01:27:02 +08:00
ShenLin 29447a41a3 revert(db)!: replace SQLite Driver with glebarez/sqlite to avoid CGO (#2269)
Revert "refactor(db)!: replace SQLite Driver with glebarez/sqlite to avoid CG…"

This reverts commit d598ef7569.
2026-03-26 21:01:48 +08:00
Jealous d85f084acb feat(permissions): implement fine-grained permission control (#2145)
* refactor(permission): rename permission check functions for clarity

- User.CanWrite() → User.CanCreateFilesOrFolders()
- common.CanWrite() → common.CanWriteContentBypassUserPerms()
- common.IsApply() → common.MetaCoversPath()

Improves code readability by making function names more descriptive.
The new MetaCoversPath name clearly indicates it checks if a meta rule
covers a specific path. It better conveys that it's a query function
rather than an action, and the applyToSubFolder parameter is more
explicit than applySub.

Also adds comprehensive test coverage:
- 10 tests for MetaCoversPath core logic
- 6 tests for CanWriteContent
UserPerms
- 7 tests for getReadme
- 5 tests for getHeader
- 6 tests for isEncrypt
- 9 tests for whetherHide

Total: 43 test scenarios covering all path matching and permission
inheritance logic. Tests verify both normal behavior and bug fixes
for Readme/Header information leakage and write permission bypass.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* feat(permission): implement fine-grained user permissions for read/write operations

Add per-user read and write permission controls at the meta level to enable
more granular access control beyond the existing permission flags.

Key changes:
- Add ReadUsers/WriteUsers fields to Meta model with sub-directory inheritance flags
- Implement CanRead and CanWrite permission check functions in server/common
- Filter file list results based on user read permissions
- Add permission checks across all file operations (FTP, HTTP handlers, WebDAV)
- Simplify error handling pattern for MetaNotFound errors throughout codebase

This allows administrators to restrict specific users from accessing or modifying
certain paths, providing finer control over file system permissions.

Note: Batch and recursive operations (FsMove, FsCopy, FsRemove, FsRecursiveMove,
FsBatchRename, FsRegexRename) currently check parent directory permissions only.
Individual item permission checks are not performed for performance reasons.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* test(permission): add comprehensive tests for CanRead, CanWrite, and combined permission checks

Add TestCanRead, TestCanWrite, TestCanAccessWithReadPermissions, and
TestWritePermissionCombinations to validate the three-layer permission
system including nil user/meta, sub-path inheritance, user whitelists,
and root-level restrictions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(webdav): use safe type assertion for MetaPassKey to prevent panic

Bearer-token and OPTIONS auth paths do not set MetaPassKey in context,
causing a panic when handlers perform a forced type assertion on nil.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(permission): treat nil user as system context in CanRead/CanWrite

Previously, CanRead/CanWrite returned false for nil user, causing
filterReadableObjs to return an empty list when fs.List is called from
internal contexts without a user (e.g. context.Background()). A nil user
represents an internal/system call and should bypass per-user restrictions,
consistent with how whetherHide already handles nil user.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(fsmanage): prevent path traversal in FsRemove

The previous check only skipped names that resolved to "/", but did not
prevent traversal to sibling directories (e.g. "../secret"), which could
bypass the CanWrite permission check that is only applied to req.Dir.

Replace with a post-join prefix check to ensure each resolved path stays
within reqPath.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(webdav): align MetaPassKey behavior with FTP auth logic

For guest users, the WebDAV password input serves as the meta folder
password (consistent with FTP anonymous/guest handling). For authenticated
users, MetaPassKey is set to empty string since their login password is
not the meta folder password.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(permission): require write auth for fs list refresh

* refactor(permission): use MetaCoversPath in CanRead/CanWrite for consistency

Replace inline `(Sub || meta.Path == path)` logic with MetaCoversPath,
consistent with CanWriteContentBypassUserPerms. Also fix a copy-paste
error in the CanWrite comment (read → write).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-03-26 14:42:35 +08:00
Pikachu Ren d598ef7569 refactor(db)!: replace SQLite Driver with glebarez/sqlite to avoid CGO (#2211)
* mod(db): driver/sqlite ->glebarez/sqlite

* mod(db): driver/sqlite ->glebarez/sqlite

* [WIP] Refactor SQLite Driver with glebarez/sqlite to avoid CGO (#2213)

* Initial plan

* fix: address review comments - fix import order, update test, remove CGO sqlite deps

Co-authored-by: PIKACHUIM <40362270+PIKACHUIM@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: PIKACHUIM <40362270+PIKACHUIM@users.noreply.github.com>

---------

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-03-25 17:45:37 +08:00
Elegant1E e41b683efb feat(drivers): add doubao_new driver (#2114) 2026-03-23 17:19:45 +08:00
Jealous 9a2ba1dabe fix(server): add missing return after error responses (#2150)
In BeginAuthnRegistration (webauthn.go), missing return statements after
error responses caused the function to continue executing with a nil
authnInstance, potentially leading to a nil pointer panic.

In OIDCLoginCallback and SSOLoginCallback (ssologin.go), missing return
statements after GenerateToken/autoRegister errors caused the handler to
send a second response, resulting in a superfluous response write.

In SetThunderBrowser (offline_download.go), the default case of the
storage type switch sent an error response but did not return, causing
SaveSettingItems and tool initialization to continue executing even when
driver type validation failed.
2026-03-16 22:22:55 +08:00
Copilot f3428e65bc fix(net): honor proxy settings when uploading to 115/115 Open/PikPak OSS (#2222)
* Initial plan

* fix: honor HTTPS proxy for OSS uploads

Co-authored-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>

* Honor HTTPS proxy settings for 115/115 Open/PikPak OSS uploads

Co-authored-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>

* revert

* chore

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: jyxjjj <773933146@qq.com>
2026-03-16 22:15:00 +08:00
Roy 5eaef96078 fix(azure): remove properties and fix prefix (#2209)
Remove properties from azure blob response

fix azure blob prefix filter: prefix should be empty if it is "/"
2026-03-09 21:25:30 +08:00
ShenLin b5626b275b chore(ci)!: update issue CI configuration [skip ci] (#2166) 2026-02-25 16:32:09 +08:00
MadDogOwner 795a18b565 feat(drivers/thunder*): implement GetDetails (#2113)
Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-02-21 15:21:05 +08:00
MadDogOwner 82ae2d5890 chore(handles/auth): improve error response (#2148)
* chore(handles/auth): improve error response

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

* Apply suggestion from @xrgzs

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-02-19 17:15:40 +08:00
MadDogOwner db0e2ec103 feat(security): add SECURITY.md (#2147)
[skip ci]

Add SECURITY.md

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-02-19 17:14:55 +08:00
mkitsdts e0ee737080 fix(driver/wps): fetch all files via multiple API invocations (#2139)
fix(driver/wps): wps list all files in one request
2026-02-19 14:48:43 +08:00
LXY 0673a74302 chore(typo): fix typo in UpdateFileReq field name (#2133)
Fix typo in UpdateFileReq field name

ref: https://github.com/OpenListTeam/115-sdk-go/pull/3

Signed-off-by: LXY <767763591@qq.com>
2026-02-16 22:57:43 +08:00
jenfonro a8d1c0ddbf fix(‎drivers/quark_uc_tv) : Update error code judgment (#2080)
* fix error code

* add ErrorInfo check
2026-02-08 21:15:00 +08:00
renovate[bot] 8431c1b1e3 fix(deps): update go4.org digest to a507140 (#2095)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-08 16:26:54 +08:00
gdm257 a121f861dc feat(drivers/123open): support sha1 reuse api (#2089)
* feat(drivers/123open): support sha1 reuse api

* fix(drivers/123open): fix typos
2026-02-08 14:01:26 +08:00
MadDogOwner 6861cb4c3b chore(ci): add breaking change guideline to PR title check (#2087)
* feat(ci): add PR title validation for breaking changes

Updated regex to allow '!' for breaking changes in PR titles.

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

* chore(pr): Update PR template

Add bilingual instructions for PR title formatting.

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-02-06 21:52:06 +08:00
Shelton Zhu 5d9fc8359d fix(115_share): adjust 115 share driver for official API update (#2068)
* fix(115_share): add user agent support and update driver dependency

* fix(115): fix download error

* feat: add thumbnail support for 115 driver and 115 share

- Add Thumb() method to FileObj in 115 driver to return thumbnail URL
- Add ThumbURL field to FileObj struct in 115 share utility
- Update 115driver dependency from v1.2.2 to v1.2.3 to support thumbnail functionality
- Implement Thumb() method for 115 share FileObj to return thumbnail URL
2026-02-02 18:43:26 +08:00
Chaloemchai f542187654 fix(drivers/teldrive): enhance file listing and upload functionality with pagination and random chunk naming (#2034)
* fix(drivers/teldrive): enhance file listing and upload functionality with pagination and random chunk naming

* fix(drivers/teldrive): optimize file listing by removing unnecessary mutex and restructuring data handling

* Update drivers/teldrive/meta.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Chaloemchai <chaloemchai.yy@gmail.com>

---------

Signed-off-by: Chaloemchai <chaloemchai.yy@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-01 20:39:25 +08:00
ShenLin e3c664f81d Merge commit from fork
Co-authored-by: KirCute <951206789@qq.com>
2026-01-31 16:52:20 +08:00
ShenLin 7b78fed106 Merge commit from fork
Co-authored-by: KirCute <951206789@qq.com>
2026-01-31 16:50:32 +08:00
Hu Yuantao d685bbfa9a fix(api/remove): add validation for empty items in delete file list (#1617)
* fix(FsRemove): add validation for empty items in delete file list

If Req.Names contains an empty string item, the whole directory will be removed. As a result we need add a simple guard to prevent such cases.

Signed-off-by: huyuantao <huyuantao@ultrarisc.com>

* fix(FsRemove): enhance validation to prevent unintended directory deletion

1. Use `utils.FixAndCleanPath` to correctly identify and block invalid names.
2. Change error handling from `return` to `continue`.

Signed-off-by: huyuantao <huyuantao@ultrarisc.com>

---------

Signed-off-by: huyuantao <huyuantao@ultrarisc.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-01-29 21:48:16 +08:00
mkitsdts 27732ccc88 fix(drivers/quark): apply html escaping in quark (#2046)
* fix(drivers/quark): apply html escaping in quark
2026-01-29 21:30:17 +08:00
MadDogOwner 29fcf5904a fix(drivers/cloudreve_v4): add IsFolder attribute to Getter response (#2035)
* fix(drivers/cloudreve_v4): add IsFolder attribute to Getter response

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

* refactor(drivers/cloudreve_v4): implement File.fileToObject method

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

* fix(drivers/cloudreve_v4): implement 404 not found for getter

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-01-28 19:30:52 +08:00
KirCute f0e53d18a8 fix(drivers/alias): default sort & substitute link (#1917)
* fix(drivers/alias): default sort & substitute link

* fix

* fix
2026-01-26 19:31:09 +08:00
Rui Huang a2573fb285 fix(drivers/seafile): object not found when RootFolderPath != "/" (#2010)
* fix(driver/seafile): object not found when RootFolderPath != "/"

* refactor(seafile): restructure Seafile driver for improved library handling and error management

* add IsDir method to LibraryInfo type

* improve initialization

* add repoID to RepoItemResp and update List method to set repoID

---------

Co-authored-by: Khoray <hhkorm@gmail.com>
Co-authored-by: j2rong4cn <j2rong@qq.com>
2026-01-25 17:00:32 +08:00
hcrgm 031b719bb0 perf(baidu_netdisk): reduce the number of file listing requests (#2016)
* 本优化减少了百度网盘驱动下文件列表的请求次数,能加快文件浏览速度。此前只要文件夹下有至少一个文件,都会至少发出2次列表请求。

Signed-off-by: hcrgm <hcrgm@qq.com>
2026-01-25 16:47:03 +08:00
mkitsdts d8417e050c fix(webdav/move): fix source file still exist after moving file by webdav (#1979) 2026-01-21 17:27:19 +08:00
Cp0204 02aec71383 fix(driver/quark_uc): Fix display of non-compliant filenames (#2000) 2026-01-20 19:30:44 +08:00
MadDogOwner fca993a830 feat(drivers/cloudreve): implement GetDetails (#1960) 2026-01-20 00:49:00 +08:00
Tron a79d8347bd fix(fs): handle non-existent destination directory in file transfer (#1898)
* fix(FileTransferTask): skip copying if destination directory does not exist

* pass only object not found error

---------

Co-authored-by: cyk <dr_arc@163.com>
Co-authored-by: KirCute <951206789@qq.com>
2026-01-17 20:12:31 +08:00
KirCute f057846e01 feat(drivers): add autoindex driver (#1978)
* feat(drivers): add autoindex driver

* fix

* add NoUpload

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

* add TestParseSize

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

* go mod tidy

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

* use base.RestyClient

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

* fix: support evaluate size and modified time

* fix apache

* perf

* feat: support ignore size and modified time

* rename driver

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2026-01-17 20:08:32 +08:00
KirCute 27fdd03ec3 fix(ci): change unchecked regex (#1993)
fix(ci/issue): change unchecked regex

Signed-off-by: KirCute <951206789@qq.com>
2026-01-17 20:00:43 +08:00
Seven ea4b5e3251 fix(drivers/strm): delete extra local directories in sync mode (#1980) 2026-01-16 15:52:04 +08:00
KirCute 378e37b082 fix(drivers/github): failed to get objs (#1915)
fix(drivers/github): failed get objs
2026-01-16 12:07:27 +08:00
MadDogOwner 5c82f55200 feat(drivers/cloudreve_v4): implement Getter interface (#1937)
feat(cloudreve_v4): implement Getter interface

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-01-16 12:05:53 +08:00
KirCute b553dc35b6 fix(drivers/ftp): failed to get objs (#1948)
fix(drivers/ftp): failed get objs
2026-01-16 12:04:55 +08:00
Ljcbaby e6db0bd6ed chore(.github): update issue templates [no ci] (#1976)
chore(.github): update issue templates
2026-01-16 12:02:45 +08:00
KirCute 85c69d853f fix(fs): panic when failed to get storage details (#1964) 2026-01-13 22:01:35 +08:00
MadDogOwner c6bd437242 feat(drivers/webdav): add support for 302 redirects (#1952)
* Remove the `OnlyProxy` restriction and obtain the redirected link to support 302

* Add `driver.Config` `PreferProxy` to recommend user to enable the proxy by default

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-01-11 15:15:42 +08:00
KirCute e192149480 fix(drivers/alist_v3): failed to unmarshal MeResp (#1931) 2026-01-08 10:54:14 +08:00
TwoOnefour 0d99e16b59 fix(cloudreve): Manually set path to avoid empty path (#1933) 2026-01-08 10:53:09 +08:00
KirCute 744dbd5e26 feat(drivers): support getting disk usage of some drivers (#1905)
* feat(drivers): support getting disk usage of some drivers

* feat(drivers/degoo): implement GetDetails

* fix(fs/storage-details): fill used space rather than free space

* fix mega

* fix bsize type
2026-01-08 10:47:22 +08:00
Seven 7088fa1f69 chore(strm): remove redundant param (#1929) 2026-01-07 18:34:33 +08:00
mcxiedidi 642acf8bca feat(123pan): add offline download (#1911)
* feat(123网盘): 添加123网盘离线下载功能

- 新增123网盘离线下载实现
- 添加相关API接口和常量配置
- 在路由和工具集中集成123网盘支持

* refactor(offline_download): 重构123网盘离线下载状态处理和类型定义

- 将离线下载相关类型定义从util.go移至types.go
- 更新状态获取api

* 移除了备选方案(/offline_download/task/status)
2026-01-04 23:13:38 +08:00
KirCute 747993e2ca feat(drivers/mega): support permanently deleting files (#1913) 2026-01-04 23:07:59 +08:00
KirCute 1f9a7e3a91 feat(drivers/mega): support getting disk usage (#1903)
* feat(drivers/mega): support getting disk usage

* fix
2026-01-04 13:26:26 +08:00
MadDogOwner 874234449b fix(doubao_share): use new download info (#1890)
fix(doubao_share): update file URL retrieval to use new download info structure

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-01-01 22:29:03 +08:00
Edward 5fe267089a fix(123_open): infinite recursive call (#1854)
fix(123_open): token refresh logic

Fix token handling logic to avoid deadlock. Token method took reference of Alist's implementation.
2025-12-31 00:46:54 +08:00
KirCute 2442e302ad ci(lang): sync only new fields (#1881) 2025-12-30 15:43:30 +08:00
Tron 0612271732 fix(driver): fix file copy failure to 123pan due to incorrect etag (#1874) 2025-12-29 23:54:33 +08:00
我怎么就不是一只猫呢? c261ce78fb fix(s3): use current time as default modified time (#1860) 2025-12-29 23:52:35 +08:00
KirCute 7398e7d45e feat(alias): support load balance (#1767)
* feat(alias): support load balance

* feat(alias): support storage match for load balance

* feat(patch): add alias addition upgrade patch

* fix bugs

* fix(op/balance): optimize compatibility

* chore: change default read conflict policy

* feat(alias): refactor Alias initialization and enhance path handling

* feat(alias): enhance object masking and add support for operation restrictions

* feat(alias): enhance object masking

* feat(fs): add permission checks

* improve parsing

* update object masks

* feat(fs): enhance virtual file handling

* feat(storage): enhance virtual file retrieval and path handling

* refactor(alias): rename path handling functions for clarity and consistency

* fix(alias): update path handling in Other method to use balanced path

* fix bug

* feat(alias): add file size validation

* feat(alias): add hash consistency check

* 移除哈希合并,

* fix(alias): wrong behavior for all_strict/deterministic_or_all

* Revert "fix(alias): wrong behavior for all_strict/deterministic_or_all"

This reverts commit f001f2dcd7.

* fix(alias): wrong behavior for all_strict/deterministic_or_all

* feat(alias): support part-based read load balance

* fix(alias): list panic when leak conflict path

* fix(alias): remove Other load balance

* fix(alias): 修复 Link 方法中 resultLink 的返回类型和内容复制问题

* fix(alias): 更好的下载并发?

* chore(alias): all tips

* fix(alias): moving paths mismatch

---------

Co-authored-by: j2rong4cn <j2rong@qq.com>
Co-authored-by: ShenLin <773933146@qq.com>
2025-12-29 17:16:07 +08:00
KirCute 6e2d499ca9 refactor(bootstrap): fix OpenList-Mobile compile failed (#1857) 2025-12-24 18:46:13 +08:00
绎泽 4680ece2d9 docs(readme): add demo site (#1850)
Last Sync: 2025-12-22 12:39
2025-12-22 12:52:41 +08:00
Seven 8a4f3769d8 feat(strm): add save local mode (#1814)
* feat(strm): add KeepSameNameOnly logic

* chore(strm): skip update strm file when keepLocalDownloadFile

* feat(strm): add save local mode
2025-12-22 10:12:21 +08:00
foxxorcat cc5172e70b fix(weiyun): update sdk and support getDetails (#1845) 2025-12-22 00:20:07 +08:00
XZB-1248 a32ae97860 docs: update README for zh-CN (#1844) 2025-12-22 00:16:33 +08:00
TwoOnefour d6dd62dfe5 fix(s3): incorrect copy key with plus sign (#1820) 2025-12-22 00:15:58 +08:00
XZB-1248 216f071e64 docs: add VPS.Town as sponsor to all README (#1842)
Co-authored-by: XZB-1248 <i@1248.ink>
2025-12-21 12:26:03 +08:00
hshpy f47df5f9b2 feat(115_open): support custom pagesize (#1822) 2025-12-20 13:57:02 +08:00
KirCute ff3c4b885c fix(strm): support generate strm with sign (#1832) 2025-12-20 13:55:51 +08:00
MadDogOwner f86c7c844c feat(cloudreve_v4): add ks3 support (#1828)
Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2025-12-19 18:05:11 +08:00
Mako (XSpy) 5db2172ed6 feat(driver): add personal / business wps drive support (#1802)
* feat(driver): add wps drive support

* feat(driver): add wps drive support

* fix(wps): update personal mode string to English

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

* fix(wps): remove trailing slash from drive origin URL

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

* fix(wps): correct order of options in mode selection

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

* fix(wps): enable local sort and upload overwrite

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

* fix(wps): resolve put bugs, fix file op problems and optimize list logic

- Fix uploading bugs. Support all uploading methods based on 8825.85d3c864.js
- Fix issues in delete/copy/move while opearting big folders.
- Use cache to optimize performance of list, especially in a deep path.

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2025-12-15 21:49:01 +08:00
wongz c4c121befc fix(139): disk-usage unmarshal failed when used capacity overflow (#1718)
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2025-12-15 21:30:08 +08:00
UcnacDx2 b4542753ba feat(drivers/139): user authentication and file batch operations (#1534)
* feat(139): Enhance 139 driver with password login and root path handling

- Added support for password-based login in the 139 driver.
- Introduced RootPath field to store the root directory path.
- Updated Init method to handle family and group types more effectively.
- Implemented new methods for handling file operations in family and group contexts.
- Enhanced error handling and logging for better debugging.
- Added new request and response structures for batch operations and document modifications.
- Improved encryption and decryption methods for secure communication.

* Update drivers/139/util.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: UcnacDx2 <127503808+UcnacDx2@users.noreply.github.com>

* Update drivers/139/util.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: UcnacDx2 <127503808+UcnacDx2@users.noreply.github.com>

* Update drivers/139/util.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: UcnacDx2 <127503808+UcnacDx2@users.noreply.github.com>

* Update drivers/139/util.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: UcnacDx2 <127503808+UcnacDx2@users.noreply.github.com>

* Update drivers/139/util.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: UcnacDx2 <127503808+UcnacDx2@users.noreply.github.com>

---------

Signed-off-by: UcnacDx2 <127503808+UcnacDx2@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-15 19:38:33 +08:00
KirCute 2a99c97d52 feat(ldap): support webdav, ftp and sftp login (#1746)
* feat(ldap): support webdav, ftp and sftp login

* fix: apply suggestions of Copilot

* feat(ldap) support ftp, sftp and webdav auto-register
2025-12-15 16:53:38 +08:00
MadDogOwner 0a407c3d8b fix(openlist): disable status check for openlist driver (#1757)
* fix(openlist): disable status check to avoid network stability issues

* fix(alist_v3): disable status check to avoid network stability issues

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2025-12-15 16:48:05 +08:00
KirCute b2596fdc24 refactor(bootstrap): move booting logic to bootstrap package (#1773)
* refactor(bootstrap): move booting to bootstrap package

* chore(log): reduce level of some callings of `utils.Log.Fatal`

* fix(s3): no shutdown after SIGTERM received

* fix: add handle hook
2025-12-15 16:47:50 +08:00
zzzhr1990 2dbe1b00d3 fix(halalcloud_open): halal-cloud upload issues (#1800)
fix halal-cloud upload issues
2025-12-15 16:47:09 +08:00
KirCute 1fc9c83df1 fix(ilanzou): parse vip size (#1792) 2025-12-12 12:13:42 +08:00
j2rong4cn d31e1a333d feat(model): add object mask support and enhance cache/task handling (#1743) 2025-12-11 15:10:42 +08:00
jenfonro e1bba7072b fix(task): tasks keep being cancelled (#1745)
* fix_cancel

* update(go.mod): update tache version

* tache v0.2.2

---------

Co-authored-by: j2rong4cn <j2rong@qq.com>
2025-12-10 19:09:16 +08:00
MadDogOwner 94c7d68413 feat(utils): add support for ignoring '@eaDir' system files (#1779) 2025-12-10 13:45:14 +08:00
KirCute 9ed77a5875 feat(driver): add AList v3 (#1721)
* feat(driver/openlist): compatible with AList v3

* Revert "feat(driver/openlist): compatible with AList v3"

This reverts commit 90f3f80186.

* feat(driver): add AList v3

* Revert "feat(patch): add migration from Alist V3 driver to OpenList (#919)"

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2025-12-08 22:25:10 +08:00
varg1714 7d6d3b8f55 feat(fs): Support customizing the cache time for a specific path (#1533)
* feat(fs): Support customizing the cache time for a specific path

* feat(fs): Get the cache rule for driver information.

* feat(fs): Support globbing.

* feat(fs): Add log.

---------

Signed-off-by: ShenLin <773933146@qq.com>
Co-authored-by: ShenLin <773933146@qq.com>
2025-12-04 09:59:27 +08:00
ShenLin 5480d61f70 refactor!(userAgent): merge most userAgent into base (#1722)
refactor!(userAgent): merge all userAgent into base

1. change var to const
2. remove duplicated ua definetion after original Resty R
3. upgrade Chrome and OS versions
2025-12-04 09:54:14 +08:00
j2rong4cn 96cd714385 refactor(op): remove automatic Path assignment (#1734)
* refactor: 移除 ObjResp 中的 Id 和 Path 字段

* 移除op.List的自动设置Path
Path和Id只在驱动内使用,不应由op.List设置Path

* cnb_releases:将 Addition 结构体中的 RootPath 字段为 RootID
当List方法加载二级目录时,若使用的是Id,应对使用driver.RootID

* doubao_share: 添加潜在bug注释

* 添加 GetRootPath 方法到多个驱动
2025-12-03 00:55:40 +08:00
VXTLS e29d92f92e fix(mediafire): enable automatic session token acquisition and fix gzip parsing (#1661)
* fix(mediafire): enable automatic session token acquisition and fix gzip parsing

- Fix Init() method to allow automatic session token retrieval from cookie
- Change SessionToken from required to optional in configuration
- Add proper gzip decompression support for API responses
- Improve error handling for session token acquisition failures
- Update help text to clarify authentication requirements

Resolves initialization failure and JSON parsing errors when session token
can be automatically obtained from browser cookie.

* fix(mediafire): ensure driver files end with newline

* chore: gofmt drivers/mediafire/*.go
2025-12-02 12:13:39 +08:00
ShenLin c5f57bbcc5 fix(drivers/crypt): remove hard dependency on RemotePath (#1713) 2025-11-28 01:21:22 +08:00
j2rong4cn 9835afc645 refactor: improve upload handling (#1455)
* fix(quark): refactor upPart to use http.NewRequest

* fix(quark): improved upload handling

* fix(quark_open): improved upload handling

* fix: add retry context to multiple upload functions

* fix: optimize hash calculation in multipart upload to avoid blocking

* fix: update error handling in lifecycle functions for better clarity

* fix: update upload progress calculation to improve accuracy

* fix: simplify error handling in lifecycle functions for improved readability

* fix: remove unnecessary mutex for part uploads to simplify code

* fix(stream): simplify file handling in NewStreamSectionReader and improve error messages

* fix(terabox): optimize chunk count calculation in Put method

* perf(chaoxing): 表单上传文件0拷贝

* fix(cnb_releases): improve file upload progress tracking

* fix(baidu_netdisk): improve upload handling

* fix(upload): optimize buffer initialization for file uploads

* fix(baidu_netdisk): add retry condition to skip ErrUploadIDExpired in upload loop
2025-11-27 19:34:03 +08:00
Seven 1f373eac8d chore(strm): avoid generating empty folders (#1720)
chore(strm): empty folders are not generated locally
2025-11-27 14:02:11 +08:00
jenfonro ede96a314c fix(onedrive_shareurl): Reduce temporary file errors (#1686)
* fix onedrive_shareurl

* .
2025-11-25 21:43:17 +08:00
Seven 72206ac9f6 feat(strm): keep local download file (#1707) 2025-11-25 18:08:48 +08:00
ShenLin 62dedb2a2e fix(pkg/aria2): use pointer receivers for Call methods (#1706) 2025-11-25 13:25:42 +08:00
ShenLin 7189c5b461 chore(pkg/aria2): simplify context cancellation handling in RPC calls (#1705) 2025-11-25 13:09:04 +08:00
ShenLin 1a445f9d3f chore(archive): fix struct literal uses unkeyed fields (#1704) 2025-11-25 13:05:36 +08:00
ShenLin aa22884079 fix(search): fix duplicated variable init (#1703) 2025-11-25 12:23:25 +08:00
ImoutoHeaven 316d4caf37 feat(search): Add task queue for Meilisearch to prevent race conditions (#1423)
* Add task queue for Meilisearch to prevent race conditions

- Implement TaskQueueManager for async index operations
- Queue update tasks and process them in batches every 30 seconds
- Check pending task status before executing new operations
- Optimize batch indexing and deletion logic
- Fix type assertion bug in buildSearchDocumentFromResults

* fix(search): re-enqueue skipped tasks to prevent task loss

When tasks are skipped due to pending dependencies, they are now
re-enqueued if not already in queue. This prevents task loss while
avoiding overwriting newer snapshots for the same parent.

* fix(copilot-comment): Invoke Stop() & err of SliceConvert

---------

Co-authored-by: ImoutoHeaven <noreply@imoutoheaven.org>
Co-authored-by: jyxjjj <773933146@qq.com>
2025-11-25 11:38:27 +08:00
KirCute 60a489eb68 feat(archive): support non-overwrite decompress (#1701) 2025-11-25 10:27:29 +08:00
varg1714 b22e211044 feat(fs): Add skipExisting option to move and copy, merge option to copy (#1556)
* fix(fs): Add skipExisting option to move and copy.

* feat(fs): Add merge option to copy.

* feat(fs): Code smell.

* feat(fs): Code smell.
2025-11-24 14:20:24 +08:00
KirCute ca401b9af9 fix(local): assign non-CoW copy requests to the task module (#1669)
* fix(local): assign non-CoW copy requests to the task module

* fix build

* fix cross device
2025-11-24 14:14:53 +08:00
jenfonro addce8b691 feat(baidu_netdisk): Add shard upload timeout setting (#1682)
add timeout
2025-11-24 14:14:34 +08:00
Seven 42fc841dc1 feat(strm): custom path prefixes (#1697)
fix(strm): custom path prefixes

Signed-off-by: ShenLin <773933146@qq.com>
Co-authored-by: ShenLin <773933146@qq.com>
2025-11-24 14:11:59 +08:00
varg1714 4c0916b64b fix(strm): fix the name and type issue (#1630)
* fix(strm): fix the name and type issue

* fix(strm): update version
2025-11-24 14:05:49 +08:00
VXTLS 3989d35abd fix(misskey): folderId format validation and root directory handling (#1647)
fix(misskey): Fix folderId format validation and root directory handling
2025-11-21 12:18:54 +08:00
KirCute 72e2ae1f14 feat(fs): support manually trigger objs update hook (#1620)
* feat(fs): support manually trigger objs update hook

* fix: support driver internal copy & move case

* fix

* fix: apply suggestions of Copilot
2025-11-21 12:18:20 +08:00
Seven 3e37f575d8 fix(openlist_driver): ensure UA is correctly propagated (#1679) 2025-11-21 12:13:41 +08:00
MoYan c0d480366d fix(driver/123): initialize Platform field (#1644)
* fix(driver/123): initialization the Platform field

Signed-off-by: MoYan <1561515308@qq.com>

* Fix formatting of Platform field in Pan123

Signed-off-by: MoYan <1561515308@qq.com>

---------

Signed-off-by: MoYan <1561515308@qq.com>
2025-11-14 18:49:44 +08:00
Copilot 9de7561154 feat(upload): add optional system file filtering for uploads (#1634) 2025-11-14 14:45:39 +08:00
MadDogOwner 0866b9075f fix(link): correct link cache mode bitwise comparison (#1635)
* fix(link): correct link cache mode bitwise comparison

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

* refactor(link): use explicit flag equality for link cache mode bitmask checks

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2025-11-13 13:52:33 +08:00
KirCute 055696f576 feat(s3): support frontend direct upload (#1631)
* feat(s3): support frontend direct upload

* feat(s3): support custom direct upload host

* fix: apply suggestions of Copilot
2025-11-13 13:22:17 +08:00
ShenLin 854415160c chore(issue templates): require logs (#1626) 2025-11-12 13:04:13 +08:00
varg1714 8f4f7d1291 feat(doubao): Add rate limiting (#1618) 2025-11-11 21:59:10 +08:00
KirCute ee2c77acd8 fix(archive/zip): user specific encoding for non-EFS zips (#1599)
* fix(archive/zip): user specific encoding for non-EFS zips

* fix(stream): simplify head cache initialization and improve reader retrieval logic

* fix: support multipart zips (.z01)

* chore(deps): update github.com/KirCute/zip to v1.0.1

---------

Co-authored-by: j2rong4cn <j2rong@qq.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2025-11-10 19:08:50 +08:00
yuyamionini fc90ec1b53 fix(terabox): wrong return code used (#1547)
fix(terabox): rename, delete, copy operations sometimes failed

Signed-off-by: yuyamionini <46483865+yuyamionini@users.noreply.github.com>
2025-11-10 13:40:00 +08:00
jenfonro 7d78944d14 fix(baidu_netdisk): Fix Baidu Netdisk resume uploads sticking to the same upload host (#1609)
Fix Baidu Netdisk resume uploads sticking to the same upload host
2025-11-09 20:43:02 +08:00
jenfonro f2e0fe8589 refactor(fs): implement immediate retry within task execution cycle (#1575) 2025-11-07 19:11:11 +08:00
ASLant 39dcf9bd19 feat(onedrive): support frontend direct upload (#1532)
* OneDrive添加直连上传

* refactor

* fix: duplicate root path join

---------

Co-authored-by: KirCute <951206789@qq.com>
2025-11-06 23:22:02 +08:00
Seven 25f38df4ca fix(strm): non-specified type generates strm (#1585)
* fix(strm): non-specified type generates strm

* fix(strm): only insert to strmTrie if SaveStrmToLocal is enabled

* fix(strm): update suffix handling in convert2strmObjs function

* fix(strm): refactor generateStrm to use range reader

---------

Co-authored-by: j2rong4cn <j2rong@qq.com>
2025-11-06 20:58:43 +08:00
j2rong4cn a1f1f98f94 refactor(stream): simplify code (#1590)
* refactor(stream): simplify Close method and update SeekableStream to use RangeReader interface

* refactor(stream):  improve RangeRead comments for clarity
2025-11-06 20:06:48 +08:00
KirCute affc499913 fix(189): disk-usage unmarshal failed when used capacity overflow (#1577) 2025-11-05 12:35:51 +08:00
KirCute c7574b545c feat(github_release): support Source code (zip/tar.gz) (#1581)
* support Github Release Source code (zip/tar.gz)

* fix TarballUrl and ZipballUrl

* fix show source code by allversion

---------

Co-authored-by: nibazshab <44338441+nibazshab@users.noreply.github.com>
2025-11-05 12:30:05 +08:00
hcrgm 9e852ba12d fix(baidu_netdisk): improve upload experience (#1562)
* fix(baidu_netdisk): improve upload experience

* fix(typo): URL should be uppercase, apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: ShenLin <773933146@qq.com>

* fix(typo): URL should be uppercase, apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: ShenLin <773933146@qq.com>

* fix(baidu_netdisk): use "UploadAPI" as a fallback when using dynamic upload api

* fix(baidu_netdisk): all uploads share the same upload url cache

* fix(drivers/baidu_netdisk): defer uploadUrlMu unlock

* update driver.go to main

---------

Signed-off-by: ShenLin <773933146@qq.com>
Signed-off-by: jenfonro <799170122@qq.com>
Co-authored-by: ShenLin <773933146@qq.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: jenfonro <799170122@qq.com>
2025-11-05 12:21:32 +08:00
j2rong4cn 174eae802a perf(stream): optimize CacheFullAndWriter for better memory management (#1584)
* perf(stream): optimize CacheFullAndWriter for better memory management

* fix(stream): ensure proper seek handling in CacheFullAndWriter for improved data integrity
2025-11-05 12:16:09 +08:00
KirCute b9f058fcc9 fix(backup-restore): add shares (#1500) 2025-11-05 12:11:20 +08:00
j2rong4cn 6de15b6310 feat(stream): enhance GetRangeReaderFromLink rate limiting (#1528)
* feat(stream): enhance GetRangeReaderFromLink rate limiting

* refactor(stream): update GetRangeReaderFromMFile to return *model.FileRangeReader

* refactor(stream): simplify context error handling in RateLimitReader, RateLimitWriter, and RateLimitFile

* refactor(net): replace custom LimitedReadCloser with readers.NewLimitedReadCloser

* fix(model): update Link.ContentLength JSON tag for correct serialization

* docs(model): add clarification to FileRangeReader usage comment
2025-11-04 23:56:09 +08:00
jenfonro 2844797684 fix(baidu_netdisk): support resuming uploads when an error occurs (#1279)
support resuming uploads when an error occurs
2025-11-04 13:33:33 +08:00
Seven 9f4e439478 chore(strm): Built-in file types support modification (#1483) 2025-11-04 10:33:16 +08:00
jenfonro 9d09ee133d fix(google_driver): fix google link file display size (#1335)
* fix file link display size

* fix performance and field

* cn to en notes

---------

Co-authored-by: ShenLin <773933146@qq.com>
2025-11-04 09:26:20 +08:00
jenfonro d88f0e8f3c feat(net): support proxy configuration via config file (#1359)
* support proxy

* debug

* debug2

* del debug

* add proxy configuration with env var fallback

* comments to en

* refactor(env): fallback env

---------

Co-authored-by: jyxjjj <773933146@qq.com>
2025-11-04 09:01:35 +08:00
ex-hentai 0857478516 feat(thunder): allow setting space (#1219)
allows access to files on remote devices via Thunder's tunneling service.
2025-11-03 10:53:38 +08:00
Seven 66d9809057 feat(strm): strm local file (#1127)
* feat(strm): strm local file

* feat: 代码优化

* feat: 访问被strm挂载路径时也更新

* fix: 路径最后带/判断缺失

* fix: 路径最后带/判断缺失

* refactor

* refactor

* fix: close seekable-stream in `generateStrm`

* refactor: lazy create local file

* 优化路径判断

---------

Co-authored-by: KirCute <kircute@foxmail.com>
2025-11-03 10:48:15 +08:00
MoYan db8a7e8caf feat(123): allow modification of the platform header (#1542)
* feat(drivers/123): Allow modification of the platform field

* feat(drivers/123): Set login platfrom as web

* fix(drivers/123): update platform field help value
2025-11-03 10:02:52 +08:00
walloo 8f18e34da0 fix(alias): nil panic in ResolveLinkCacheMode (#1527)
* fix(alias): Check the driver path during initialization

* fix(alias): Don't check the driver path during initialization anymore.
2025-10-23 22:18:56 +08:00
ShenLin 525f26dc23 feat(command): add --config flag to set custom config path (#1479) 2025-10-22 19:35:34 +08:00
NewbieOrange a0fcfa3ed2 fix(aliyundrive_open): use safe disk usage calculation (#1510) 2025-10-20 22:05:14 +08:00
ILoveScratch 15f276537c fix(share): remove share when user delete (#1493) 2025-10-19 22:48:21 +08:00
MadDogOwner 623a12050e feat(openlist): add PassIPToUpsteam to driver (#1498) 2025-10-19 22:45:40 +08:00
D@' 3z K!7 ae2d2d1021 feat(drivers): add ProtonDrive driver (#1368)
* feat(drivers): add ProtonDrive driver

- Implement complete ProtonDrive storage driver with end-to-end encryption support
- Add authentication via username/password with credential caching and reusable login
- Support all core operations: List, Link, Put, Copy, Move, Remove, Rename, MakeDir
- Include encrypted file operations with PGP key management and node passphrase handling
- Add temporary HTTP server for secure file downloads with range request support
- Support media streaming using temp server range requests
- Implement progress tracking for uploads and downloads
- Support directory operations with circular move detection
- Add proper error handling and panic recovery for external library integration
- Support buffered upload for specific sequential and encrypted, but optimized transmission.

* Update drivers/proton_drive/util.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: D@' 3z K!7 <99719341+Da3zKi7@users.noreply.github.com>

* chore

* feat(drivers): enhance ProtonDrive temp server

- Implement separate listen and public port configuration for complex network deployments
- Add intelligent port detection with 8080 as preferred default, fallback to auto-assignment
- Support Container/NAT/VM environments through configurable external host and port mapping
- Add port availability validation with graceful fallback to listen port
- Enable users to specify external domain/IP for client connections (e.g., 192.168.1.5)
- Follow FTP server configuration patterns for network flexibility
- Maintain localhost development simplicity while supporting production deployments

* feat(proton_drive): refactor directory handling and improve link retrieval

* fix(proton_drive): add NoLinkURL configuration option

* fix(proton_drive): update file size retrieval and enforce TwoFACode requirement

* feat(proton_drive): add expiration to link response

* fix(proton_drive): handle empty RootFolderID in Init method

* fix(proton_drive): update credential handling to use email and reusable login

* fix(proton_drive): update credential handling to use reusableCredential variable

* fix(proton_drive): update DirectRename to use GetLink for source object retrieval

* fix(proton_drive): refactor uploadFile to return model.Obj and handle errors correctly

* fix(proton_drive): refactor DirectMove to use getLink for source retrieval and simplify destination handling

* fix(proton_drive): simplify Copy method by removing temporary file creation and directly using FileStream

* refactor(proton_drive): remove unused temporary server and related code

* chore

* fix(proton_drive): fix driver

- Handle fresh login if ProtonDrive rejects AccessToken or RefreshToken
- Update stored credentials

* fix(proton_drive): simplify reusable login handling in Init method

* fix(proton_drive): fix driver

- Update stored credentials, now is failing

* feat(proton_drive): improve authentication handling and remove unused variables

* fix(proton_drive): fix driver

- Update stored credentials, now is failing

* fix(proton_drive): improve authentication handling

* refactor(proton_drive): move client initialization to initClient method

* feat(proton_drive): move addrs and addrKRs

* feat(proton_drive): optimize upload threads

- Change ConcurrentBlockUploadCount to user configured upload threads number
- Comment ConcurrentFileCryptoCount, default is runtime.GOMAXPROCS(0)

---------

Signed-off-by: D@' 3z K!7 <99719341+Da3zKi7@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: KirCute <951206789@qq.com>
Co-authored-by: j2rong4cn <j2rong@qq.com>
Co-authored-by: KirCute <kircute@foxmail.com>
2025-10-19 12:07:11 +08:00
jerrita a109152a13 feat(onedrive): add ref support (#1435)
* feat(onedrive): add ref support

* fix(onedrive): remove redundant token assignment from reference

---------

Co-authored-by: j2rong4cn <j2rong@qq.com>
2025-10-18 21:48:26 +08:00
ILoveScratch febbcd6027 feat(cache): improve cache management (#1339)
* feat(cache): improve cache management

* feat(disk-usage): add cache

* feat(disk-usage): add refresh

* fix(disk-usage): cache with ttl

* feat(cache): implement KeyedCache and TypedCache for improved caching mechanism

* fix(copy): update object retrieval to use Get instead of GetUnwrap

* refactor(cache): simplify DirectoryCache structure and improve object management

* fix(cache): correct cache entry initialization and key deletion logic in TypedCache

* refactor(driver): remove GetObjInfo interface and simplify Link function logic
https://github.com/OpenListTeam/OpenList/pull/888/files#r2430925783

* fix(link): optimize link retrieval and caching logic

* refactor(cache): consolidate cache management and improve directory cache handling

* fix(cache): add cache control based on storage configuration in List function

* .

* refactor: replace fmt.Sprintf with strconv for integer conversions

* refactor(cache): enhance cache entry management with Expirable interface

* fix(cache): improve link reference acquisition logic to handle expiration

* refactor: replace OnlyLinkMFile with NoLinkSF in driver configurations and logic

* refactor(link): enhance link caching logic with dynamic type keys based on IP and User-Agent

* feat(drivers): add LinkCacheType to driver configurations for enhanced caching

* refactor(cache): streamline directory object management in cache operations

* refactor(cache): remove unnecessary 'dirty' field from CacheEntry structure

* refactor(cache): replace 'dirty' field with bitwise flags

* refactor(io): 调高SyncClosers.AcquireReference的优先级

* refactor(link): 优化链接获取逻辑,增加重

* refactor(link): 添加RequireReference字段以增强链接管理

* refactor(link): 移除MFile字段,改用RangeReader

* refactor: 移除不必要的NoLinkSF字段

* refactor(cache): 修改目录缓存的脏标志定义和更新逻辑

* feat(cache): add expiration gc

---------

Co-authored-by: KirCute <951206789@qq.com>
Co-authored-by: KirCute <kircute@foxmail.com>
Co-authored-by: j2rong4cn <j2rong@qq.com>
2025-10-18 21:47:18 +08:00
jenfonro 549e60136b fix(fs):fix retry task after restart (#1467)
* fix retry task after restart

* fix: initialize SrcStorage and DstStorage in tasks to prevent nil pointer dereference

* feat: implement storage load signal mechanism for improved synchronization

* fix:  update StoragesLoaded logic

* refactor: reorganize storage loading logic and improve synchronization handling

---------

Co-authored-by: j2rong4cn <j2rong@qq.com>
2025-10-18 20:52:02 +08:00
Tursom K. Ulefits 14d2b8290a feat(local): move deleted files to corresponding locations (#1281) 2025-10-17 18:01:02 +08:00
ShenLin cdc069d8e7 feat(http3|quic): Set Alt-Svc header only for HTTPS requests (#1469) 2025-10-14 18:07:29 +08:00
zzzhr1990 fb5094f688 feat(drivers): add halalcloud_open driver (#1430)
* 新增清真云Open驱动,支持最新的轻量SDK

* Change Go version in go.mod

Downgrade Go version from 1.24.2 to 1.23.4

Signed-off-by: zzzhr1990 <zzzhr@hotmail.com>

* Apply suggestions from code review

* Removed unnecessary comments
* Downgraded the Go version to 1.23.4.
* Not sure whether FileStream supports concurrent read and write operations, so currently using single-threaded upload to ensure safety.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: zzzhr1990 <zzzhr@hotmail.com>

* feat(halalcloud_open): support disk usage

* Set useSingleUpload to true for upload safety

Not sure whether FileStream supports concurrent read and write operations, so currently using single-threaded upload to ensure safety.

Signed-off-by: zzzhr1990 <zzzhr@hotmail.com>

* Update meta.go

Change required for RefreshToken, If using a personal API approach, the RefreshToken is not required.

Signed-off-by: zzzhr1990 <zzzhr@hotmail.com>

* remove debug logs

* bump halalcloud SDK version

* fix unnecessary params

* Update drivers/halalcloud_open/driver_init.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: zzzhr1990 <zzzhr@hotmail.com>

* Fixed spelling errors; changed hardcoded retry parameters to constants.

* remove pointer in get link function in utils.go

---------

Signed-off-by: zzzhr1990 <zzzhr@hotmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: KirCute <951206789@qq.com>
2025-10-14 16:03:42 +08:00
KirCute 670e0bdc45 chore(frontend): optimize user operations (#1449) 2025-10-14 16:02:50 +08:00
ShenLin 89235012af feat(http3|quic): add http3|quic support (#1466)
* feat(http3|quic): add http3|quic support

* revert(ai): fix ai error

* fix(shutdown): shutdown was using close

* feat(http3|quic): add config if needs h3

* feat(http3|quic): add Alt-Svc to expose h3
2025-10-14 15:57:16 +08:00
KirCute 2bfbad2874 feat(offline_download): add 123 open (#1427) 2025-10-07 01:13:25 +08:00
KirCute 4ba7696032 feat(pikpak): support disk usage (#1426)
* feat(pikpak): support disk usage

* fix(alias): cannot list with details

* refactor: rename `NewDiskUsageFromUsedAndTotal`

* fix(disk-usage): get details of storages that is not initialized
2025-10-06 16:37:00 +08:00
KirCute 66645516e5 fix(ilanzou): wrong total capacity (#1433) 2025-10-06 16:35:10 +08:00
KirCute eb2ff2d2ca fix(189pc/189tv): request panic when login failed (#1428) 2025-10-05 22:44:50 +08:00
NewbieOrange 4153245f2c fix(drivers): free space underflow if used larger than total space (#1407) 2025-10-04 00:41:45 +08:00
KirCute 6fe9af7819 fix(alias): stabilize list root result (#1401) 2025-10-01 21:05:04 +08:00
j2rong4cn 2edc446ced feat(stream): support using temporary files as large buffer (#1399)
feat(stream): refactor StreamSectionReader to support using temporary files as large buffer
2025-10-01 18:43:20 +08:00
j2rong4cn c3c7983f7b perf(sync-closers): improve Close method (#1395)
Signed-off-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-01 18:06:10 +08:00
HG-ha 22deb4df30 fix(lanzou): auto handle acw_sc__v2 and down_ip=1 for all requests, improve secondary validation (#1394)
* Refactor upload and request handling in util.go

重构请求部分以避免偶现failed link: failed get link:的情况

Signed-off-by: HG-ha <60115106+HG-ha@users.noreply.github.com>

* Format and clean up code in util.go

Signed-off-by: HG-ha <60115106+HG-ha@users.noreply.github.com>

* go fmt util.go

---------

Signed-off-by: HG-ha <60115106+HG-ha@users.noreply.github.com>
2025-10-01 17:38:50 +08:00
j2rong4cn da0c734aa3 fix(net): unable to pass HttpStatusCode (#1397) 2025-10-01 00:16:36 +08:00
ILoveScratch 189cebe4c9 feat(drivers): add MediaFire driver support (#1322)
* feat(drivers): add MediaFire driver support (#9319)

- Implement complete MediaFire storage driver
- Add authentication via session_token and cookie
- Support all core operations: List, Get, Link, Put, Copy, Move, Remove, Rename, MakeDir
- Include thumbnail generation for media files
- Handle MediaFire's resumable upload API with multi-unit transfers
- Add proper error handling and progress reporting

Co-authored-by: Da3zKi7 <da3zki7@duck.com>

* fix(mediafire): fix code errors in mediafire

* fix(mediafire): fix code errors in mediafire

* fix(drivers): add session renewal cron for MediaFire driver (#9321)

- Implement automatic session token renewal every 6-9 minutes
- Add validation for required SessionToken and Cookie fields in Init
- Handle session expiration by calling renewToken on validation failure
- Prevent storage failures due to MediaFire session timeouts

Fixes session closure issues that occur after server restarts or extended periods.

Co-authored-by: Da3zKi7 <da3zki7@duck.com>

* docs: restore README changes

Signed-off-by: ILoveScratch <ilovescratch@foxmail.com>

* fix

* fix

* fix: add stream upload limit

* fix

* fix: clear action token on drop and refactor header setting

* feat(drivers/mediafire): optimize file caching - support direct stream processing

- Remove forced caching to *os.File type
- Support generic model.File interface for better flexibility
- Improve upload efficiency by avoiding unnecessary file conversions
- Fix return type to use model.Object instead of model.ObjThumb

* feat(drivers/mediafire): improve global rate limiting

- Ensure all API methods properly use context for rate limiting
- Fix context parameter usage in getDirectDownloadLink, getActionToken, getFileByHash
- Maintain consistent rate limiting across all MediaFire API calls

* feat(drivers/mediafire): unify return types - remove unnecessary ObjThumb

- Change MakeDir, Rename, Copy methods to return model.Object instead of model.ObjThumb
- Remove empty Thumbnail fields where not meaningful
- Keep ObjThumb only for fileToObj (List operations) which provides actual thumbnail URLs
- Improve code consistency and reduce unnecessary wrapper objects

* refactor(drivers/mediafire): extract common error handling logic

- Add checkAPIResult helper function to reduce code duplication
- Replace repetitive MediaFire API error checks with centralized function
- Maintain specific error messages for unique cases (token, upload, search)
- Improve code maintainability and consistency

* enhance(drivers/mediafire): improve quick upload implementation

- Add null check for existingFile to prevent potential issues
- Improve error handling in quick upload - continue normal upload if search fails
- Add detailed comments explaining quick upload logic
- Optimize getExistingFileInfo with clearer fallback strategy
- Ensure upload reliability even when file search encounters issues

* refactor(drivers/mediafire): optimize request method reusability

- Extract common HTTP request logic into apiRequest method
- Reduce code duplication between getForm and postForm methods
- Maintain backward compatibility with existing method signatures
- Centralize rate limiting and header management
- Support extensible HTTP method handling

* docs(drivers/mediafire): add comprehensive English comments

- Add function-level comments for all major driver methods
- Document Init, List, Link, MakeDir, Move, Rename, Copy, Remove, Put methods
- Add comments for key utility functions including session token management
- Improve code readability and maintainability for community collaboration
- Follow Go documentation conventions with clear, concise descriptions

* perf(mediafire): optimize memory allocation and type assertion performance

- Pre-allocate slice capacity in getFiles and bitmap conversion to reduce reallocations
- Cache file type check in uploadUnits to avoid repeated type assertions
- Add uploadSingleUnitOptimized for os.File to eliminate redundant type checks
- Optimize string to int conversion with proper error handling
- Improve memory efficiency in file upload operations

* fix(mediafire): upload without cache

* feat(mediafire): add rate limiting to all API methods

- Add WaitLimit(ctx) calls to all driver methods: List, Link, MakeDir, Move, Rename, Copy, Remove, Put
- Ensure consistent rate limiting across all MediaFire API interactions
- Follow project standard pattern used by other drivers

* feat(mediafire): improve error handling consistency

- Add context parameter to all HTTP API functions for proper context propagation
- Update getForm, postForm and apiRequest to accept context parameter
- Fix rate limiting to use caller context instead of background context
- Ensure consistent error handling patterns across all API calls
- Improve cancellation and timeout support

* feat(mediafire): refactor resumableUpload to use io.ReadSeeker and improve upload handling

* fix(mediafire): release section reader

* feat: add disk usage

* feat(drivers/mediafire): support concurrent upload (#1387)

* feat(drivers): add MediaFire driver with concurrent upload support

- Implement complete MediaFire storage driver with session token authentication
- Support all core operations: List, Get, Link, Put, Copy, Move, Remove, Rename, MakeDir
- Include thumbnail generation for media files
- Handle MediaFire's resumable upload with intelligent and multi-unit transfers
- Support concurrent chunk uploads using errgroup.NewOrderedGroupWithContext, using splitted file caching for large files
- Optimize memory usage with adaptive buffer sizing (10MB-100MB (default))
- Include rate limiting and retry logic for API requests
- Add proper error handling and progress reporting
- Handle MediaFire's bitmap-based resumable upload protocol

Closes PR #1322

* feat(stream): add DiscardSection method to StreamSectionReader for skipping data

* feat(mediafire): refactor resumableUpload logic for improved upload handling and error management

* fix(mediafire): stop cron job and clear action token in Drop method

* .

* fix(mediafire): optimize buffer sizing logic in uploadUnits method

* fix(docs): remove duplicate MediaFire

* fix(mediafire): revert 'optimization', large files should not be fully chached.

---------

Signed-off-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
Co-authored-by: Da3zKi7 <da3zki7@duck.com>
Co-authored-by: D@' 3z K!7 <99719341+Da3zKi7@users.noreply.github.com>
Co-authored-by: j2rong4cn <j2rong@qq.com>
Co-authored-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>

* fix(mediafire): optimize hash calculation in uploadUnits function

* feat(drivers/mediafire): support concurrent upload  (#1366)

* feat(drivers): add MediaFire driver with concurrent upload support

- Implement complete MediaFire storage driver with session token authentication
- Support all core operations: List, Get, Link, Put, Copy, Move, Remove, Rename, MakeDir
- Include thumbnail generation for media files
- Handle MediaFire's resumable upload with intelligent and multi-unit transfers
- Support concurrent chunk uploads using errgroup.NewOrderedGroupWithContext, using splitted file caching for large files
- Optimize memory usage with adaptive buffer sizing (10MB-100MB (default))
- Include rate limiting and retry logic for API requests
- Add proper error handling and progress reporting
- Handle MediaFire's bitmap-based resumable upload protocol

Closes PR #1322

* feat(stream): add DiscardSection method to StreamSectionReader for skipping data

* feat(mediafire): refactor resumableUpload logic for improved upload handling and error management

* fix(mediafire): stop cron job and clear action token in Drop method

* .

* fix(mediafire): optimize buffer sizing logic in uploadUnits method

* fix(docs): remove duplicate MediaFire

* fix(mediafire): revert 'optimization', large files should not be fully chached.

---------

Signed-off-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
Signed-off-by: D@' 3z K!7 <99719341+Da3zKi7@users.noreply.github.com>
Co-authored-by: j2rong4cn <j2rong@qq.com>
Co-authored-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>

---------

Signed-off-by: ILoveScratch <ilovescratch@foxmail.com>
Signed-off-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
Signed-off-by: D@' 3z K!7 <99719341+Da3zKi7@users.noreply.github.com>
Co-authored-by: D@' 3z K!7 <99719341+Da3zKi7@users.noreply.github.com>
Co-authored-by: Da3zKi7 <da3zki7@duck.com>
Co-authored-by: KirCute <951206789@qq.com>
Co-authored-by: Suyunmeng <Susus0175@proton.me>
Co-authored-by: j2rong4cn <j2rong@qq.com>
Co-authored-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
2025-09-30 21:55:41 +08:00
j2rong4cn 9d3da44a99 fix(chunk): ensure NumListWorkers is set during Chunk initialization (#1396) 2025-09-30 21:39:19 +08:00
j2rong4cn 8f17d35ed5 feat(chunk): add ChunkPrefix and ChunkLargeFileOnly options (#1321)
* fix(chunk): move chunk existence check to Link method

* feat(chunk): add chunk prefix configuration

* feat(chunk): add chunk_large_file_only configuration

* feat(chunk): concurrently list chunk folder

* refactor(chunk): remove unnecessary mutex for result handling in List method

---------

Co-authored-by: KirCute <kircute@foxmail.com>
2025-09-30 21:26:06 +08:00
HG-ha 89759b6e3b fix(lanzou): support acw_sc__v2 and secondary validation for download link (#1379)
* 重定向链接添加acw_sc__v2验证

在最新的蓝奏云解析中,最后重定向获取真实地址时也需要添加acw_sc__v2信息

Signed-off-by: HG-ha <60115106+HG-ha@users.noreply.github.com>

* 重定向链接添加acw_sc__v2验证

Signed-off-by: HG-ha <60115106+HG-ha@users.noreply.github.com>

* 重定向真实下载链接添加acw_sc__v2验证

Signed-off-by: HG-ha <60115106+HG-ha@users.noreply.github.com>

* fix: CalcAcwScV2

* Add error handling for response body read

Handle error when reading response body.

Signed-off-by: HG-ha <60115106+HG-ha@users.noreply.github.com>

* Improve response handling and validation logic

优化重定向资源管理,添加二次人机验证acw_sc__v2处理

Signed-off-by: HG-ha <60115106+HG-ha@users.noreply.github.com>

---------

Signed-off-by: HG-ha <60115106+HG-ha@users.noreply.github.com>
Co-authored-by: foxxorcat <foxxorcat@foxmail.com>
2025-09-30 17:07:30 +08:00
KirCute a2fc38be8d perf(disk-usage): concurrently get details (#1326) 2025-09-29 23:26:56 +08:00
KirCute e0414e7110 fix(offline_download/http): attach UA to the request (#1347)
fix(simple-http): attach UA to the request
2025-09-29 22:13:00 +08:00
KirCute b486af0031 feat(sftp-server): support disable password login (#1357) 2025-09-29 21:46:55 +08:00
j2rong4cn ea09ce4b8f fix(fs): improve error handling in op.Get (#1323) 2025-09-29 21:38:34 +08:00
KirCute d465da43e3 fix(ftp-server): cannot get obj in uploading state inconsistency window (#1293)
* fix(ftp-server): cannot get obj in uploading state inconsistency window

* fix

* fix: duplicate obj when upload completed but client access does not

* fix

* feat: support stat remove and move
2025-09-23 01:00:18 +08:00
Dgs 84ed487950 feat(quark_uc_tv): add order by and direction options for file listing (#1325) 2025-09-21 20:43:32 +08:00
ILoveScratch 3c07144211 chore(announcement): change default announcement text (#1319)
* chore(announcement): change default announcement text for better clarity  

- Improve site announcement style for a more polished look
- Adjust default value to avoid unclear meaning with only repo or single link
2025-09-20 23:06:40 +08:00
KirCute 3936e736e6 feat(drivers): add a driver that divides large files into multiple chunks (#1153) 2025-09-19 19:27:35 +08:00
KirCute 68433d4f5b fix(local): cannot mkdir on specific platforms (#1304) 2025-09-19 15:34:58 +08:00
KirCute cc16cb35bf feat(style): add driver icons and disk usage (#1274)
* feat(style): add driver icons and disk usage

* feat(driver): add disk usage for 115_open, 123_open, aliyundrive_open and baidu_netdisk

* feat(driver): add disk usage for crypt, sftp and smb

* chore: clean unused variable

* feat(driver): add disk usage for cloudreve_v4

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

* fix(local): disk label check when getting disk usage

* feat(style): return details when accessing the manage page

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2025-09-19 11:59:11 +08:00
Yinan Qin d3bc6321f4 chore(build): update Go version to 1.25.0 across workflows and build scripts (#1290)
build: update Go version to 1.25.0 across workflows and build scripts

fixes #1286
2025-09-16 18:44:29 +08:00
TwoOnefour cbbb5ad231 fix(stream): http chucked upload issue (#1152)
* fix(stream): http chucked upload issue

* fix(stream): use MmapThreshold

* fix(stream): improve caching mechanism and handle size=0 case

* fix bug

* fix(buffer): optimize ReadAt method for improved performance

* fix(upload): handle Content-Length and File-Size headers for better size management

* fix(189pc): 移除重复限速

* fix(upload): handle negative file size during streaming uploads

* fix(upload): update header key from File-Size to X-File-Size for size retrieval

---------

Co-authored-by: j2rong4cn <j2rong@qq.com>
2025-09-15 19:36:16 +08:00
hshpy c1d03c5bcc fix(security): zip slip (#1228)
* fix(security): Zip Slip

* chore:remove repeat clean

* fix: archives,iso9660 and rardecode module

---------

Co-authored-by: ILoveScratch <ilovescratch@foxmail.com>
2025-09-15 13:25:21 +08:00
KirCute 61a8ed515f fix(123): add get and list hash info (#1278) 2025-09-14 21:36:54 +08:00
KirCute bbb7c06504 feat(alias): support pass through provider (#1269) 2025-09-14 21:36:38 +08:00
ILoveScratch 8bbdb272d4 docs(readme): extend driver list with newest support (#1271) 2025-09-13 20:41:17 +08:00
foxxorcat c15ae94307 feat(189PC,189TV): add refreshToken and qrcode login (#1205)
### Key Changes
- **189PC**: Add QR code login and refresh token support
- **189TV**: Add session refresh mechanism and fix TempUuid persistence issue
- **Both**: Implement session keep-alive with cron jobs (5min interval)

### Features
- QR code authentication for 189PC as alternative to password login
- Automatic token refresh to avoid frequent re-authentication
- Session keep-alive to maintain long-term connections
- Retry logic with max attempts to prevent infinite loops

### Fixes
- Fixed 189TV TempUuid causing storage corruption on QR code reload
- Enhanced error handling for token expiration scenarios
2025-09-13 13:59:47 +08:00
MadDogOwner f1a5048558 feat(drivers): add cnb_releases (#1033)
* feat(drivers): add cnb_releases

* feat(cnb_release): implement reference

* refactor(cnb_releases): get release info by ID instead of tag name

* feat(cnb_releases): add option to use tag name instead of release name

* fix(cnb_releases): set default root and improve release info retrieval

* feat(cnb_releases): implement Put

* perf(cnb_release): use io.Pipe to stream file upload

* perf(cnb_releases): add context timeout for file upload request

* feat(cnb_releases): implement Remove

* feat(cnb_releases): implement MakeDir

* feat(cnb_releases): implement Rename

* feat(cnb_releases): require repo and token in Addition

* chore(cnb_releases): remove unused code

* Revert 'perf(cnb_release): use io.Pipe to stream file upload'

* perf(cnb_releases): optimize upload with MultiReader

* feat(cnb_releases): add DefaultBranch

---------

Co-authored-by: ILoveScratch <ilovescratch@foxmail.com>
2025-09-11 18:11:32 +08:00
Tursom K. Ulefits 1fe26bff9a feat(local): auto create recycle dir if not exists (#1244) 2025-09-10 20:57:21 +08:00
Suyunjing 433dcd156b fix(ci): add tag_name to upload assets step (#1234)
fix(release): add tag_name to upload assets step
2025-09-06 22:51:05 +08:00
MadDogOwner e97f0a289e feat(cloudreve_v4): enhance token management (#1171)
* fix(cloudreve_v4): improve error handling in request method

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

* feat(cloudreve_v4): enhance token management with expiration checks and refresh logic

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

* feat(cloudreve_v4): add JWT structures for access and refresh tokens; validate access token on initialization

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

* fix(cloudreve_v4): improve error messages

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2025-09-04 19:41:41 +08:00
walloo 89f35170b3 fix(fs): clear cache after directory rename to ensure consistency (#1193)
Clear cache after renaming the directory.
2025-09-01 18:47:54 +08:00
MadDogOwner 8188fb2d7d fix(123open): get direct link (#1185)
* fix(123open): correct query parameter name from 'fileId' to 'fileID' in getDirectLink function

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

* fix(123open): change SpaceTempExpr type from 'string' to 'int64' in UserInfoResp struct

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

* fix(123open): comment out unused fields in UserInfoResp struct

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

* fix(123open): add getUID method and cache UID

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2025-08-31 15:47:38 +08:00
MadDogOwner 87cf95f50b fix(139): refactor part upload logic (#1184)
* fix(139): refactor part upload logic

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

* fix(139): handle upload errors

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

* fix(139): sort upload parts by PartNumber before uploading

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

* fix(139): improve error handling

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

* fix(139): add validation for upload part index to prevent out of bounds errors

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2025-08-31 15:47:12 +08:00
MadDogOwner 8ab26cb823 fix(123open): change DirectLink type from 'boolean' to 'bool' (#1180)
Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2025-08-29 19:06:37 +08:00
j2rong4cn 5880c8e1af fix(189tv): use rate-limited upload stream in OldUpload function (#1176)
* fix(189tv): use rate-limited upload stream in OldUpload function

* fix(189tv): wrap tempFile with io.NopCloser to prevent premature closure in OldUpload function

* .
2025-08-29 16:01:50 +08:00
KirCute 14bf4ecb4c fix(share): support custom proxy url (#1130)
* feat(share): support custom proxy url

* fix(share): count access

* fix: maybe a path traversal vulnerability?
2025-08-28 22:11:19 +08:00
hshpy 04a5e58781 fix(server): can't edit .md source files (#1159)
* fix(server): can't edit .md source files

* chore

* add ignore direct link args
2025-08-28 16:19:57 +08:00
MadDogOwner bbd4389345 fix(wopan): use fixed timezone for parsing time (#1170)
fix(wopan): update getTime function to use fixed timezone for parsing

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2025-08-28 13:02:02 +08:00
MadDogOwner f350ccdf95 fix(189pc): sliceSize must not be equal to fileSize (#1169)
* fix(189pc): sliceSize not equal to fileSize

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

* Update comment for sliceSize parameter

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2025-08-28 11:32:40 +08:00
Caspian 4f2de9395e feat(degoo): token improvement (#1149)
* Update driver.go

Signed-off-by: Caspian <app@caspian.im>

* Update meta.go

Signed-off-by: Caspian <app@caspian.im>

* Update util.go

Signed-off-by: Caspian <app@caspian.im>

* Update util.go

Signed-off-by: Caspian <app@caspian.im>

* Update util.go

Signed-off-by: Caspian <app@caspian.im>

* Update util.go

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

* make account optional

* ensure username and password

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

---------

Signed-off-by: Caspian <app@caspian.im>
Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2025-08-26 01:22:59 +08:00
TwoOnefour b0dbbebfb0 feat(drivers): add Teldrive driver (#1116)
https://github.com/tgdrive/teldrive

https://teldrive-docs.pages.dev/docs/api

实现:
* copy
* move
* link (302 share and local proxy)
* chunked uploads
* rename

未实现:
- openlist扫码登陆
- refresh token

https://github.com/OpenListTeam/OpenList-Docs/pull/155


* feat(Teldrive): Add driver Teldrive

* fix(teldrive): force webproxy and memory optimized

* chore(teldrive): go fmt

* chore(teldrive): remove TODO

* chore(teldrive): organize code

* feat(teldrive): add UseShareLink option and support 302

* fix(teldrive): standardize API path construction

* fix(teldrive): trim trailing slash from Address in Init method

* chore(teldrive): update help text for UseShareLink field in Addition struct

* fix(teldrive): set 10 MiB as default chunk size

---------

Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: ILoveScratch <ilovescratch@foxmail.com>
2025-08-25 01:34:08 +08:00
MadDogOwner 0c27b4bd47 docs(contributing): update guidelines (#983)
[skip ci]

* docs(contributing): update guidelines

* docs(contributing): clarify fork

* docs(contributing): sync translation

Co-authored-by: Yinan Qin <39023210+elysia-best@users.noreply.github.com>
Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* docs(contributing): add label and cc reminder

* docs(contributing): remove ensure new branch from checklist

* docs(contributing): replace generic GitHub URLs with user-specific ones

* docs(contributing): make branch deletion after PR merge optional

* docs(contributing): keep --recurse-submodules

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: Yinan Qin <39023210+elysia-best@users.noreply.github.com>
2025-08-24 20:13:11 +08:00
power721 736cd9e5f2 fix(quark): fix getTranscodingLink (#1136)
The first video info may not contain url

* fix(quark): fix getTranscodingLink

* fix(quark_tv): fix getTranscodingLink
2025-08-24 19:55:10 +08:00
power721 c7a603c926 fix(115): fix get 115 app version (#1137) 2025-08-24 19:50:21 +08:00
Edward a28d6d5693 fix(123_open): fix token refresh (#1121) 2025-08-23 23:01:41 +08:00
Caspian e59d2233e2 feat(drivers): add Degoo driver (#1097)
* Create driver.go

Signed-off-by: CaspianGUAN <app@caspian.im>

* Create util.go

Signed-off-by: CaspianGUAN <app@caspian.im>

* Create types.go

Signed-off-by: CaspianGUAN <app@caspian.im>

* Create meta.go

Signed-off-by: CaspianGUAN <app@caspian.im>

* Update drivers/degoo/driver.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: CaspianGUAN <app@caspian.im>

* Update drivers/degoo/driver.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: CaspianGUAN <app@caspian.im>

* Update driver.go

Signed-off-by: CaspianGUAN <app@caspian.im>

* Update meta.go

Signed-off-by: CaspianGUAN <app@caspian.im>

* Update types.go

Signed-off-by: CaspianGUAN <app@caspian.im>

* Update util.go

Signed-off-by: CaspianGUAN <app@caspian.im>

* Update driver.go

Signed-off-by: CaspianGUAN <app@caspian.im>

* Update util.go

Signed-off-by: CaspianGUAN <app@caspian.im>

* Update drivers/degoo/util.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: CaspianGUAN <app@caspian.im>

* Update util.go

Signed-off-by: CaspianGUAN <app@caspian.im>

* refactor(degoo): add Degoo driver integration and update API handling

* fix(degoo): apply suggestions

---------

Signed-off-by: CaspianGUAN <app@caspian.im>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2025-08-23 22:47:02 +08:00
我怎么就不是一只猫呢? 01914a06ef refactor(ci): add permissions check at docker's entrypoint (#1128)
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2025-08-22 19:35:48 +08:00
Shelton Zhu 6499374d1c fix(deps): update 115driver to v1.1.1 (close SheltonZhu/115driver#57) (#1115) 2025-08-20 21:33:21 +08:00
MadDogOwner b054919d5c feat(ilanzou): add support for rapid upload and fix duplication handling (#1065)
* feat(ilanzou): add support for rapid upload token handling

* feat(ilanzou): add NoOverwriteUpload option
2025-08-19 19:19:44 +08:00
KirCute 048ee9c2e5 feat(server): adapting #1099 to #991 (#1102) 2025-08-19 15:48:59 +08:00
MadDogOwner 23394548ca feat(123_open): add DirectLink option (#1045)
* feat(123_open): add `UseDirectLink` option

* feat(123_open): update rate limit rules

* fix(123_open): update api

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

* feat(123_open): enhance direct link functionality with private key and expiration

* refactor(123_open): use UUID for random generation

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-19 15:23:10 +08:00
MadDogOwner b04677b806 feat(server): add error page and status code (#1099) 2025-08-19 15:18:12 +08:00
KirCute e4c902dd93 feat(share): support more secure file sharing (#991)
提供一种类似大多数网盘的文件分享操作,这种分享方式可以通过强制 Web 代理隐藏文件源路径,可以设置分享码、最大访问数和过期时间,并且不需要启用 guest 用户。

在全局设置中可以调整:
- 是否强制 Web 代理
- 是否允许预览
- 是否允许预览压缩文件
- 分享文件后,点击“复制链接”按钮复制的内容

前端部分:OpenListTeam/OpenList-Frontend#156
文档部分:OpenListTeam/OpenList-Docs#130

Close #183
Close #526
Close #860
Close #892
Close #1079


* feat(share): support more secure file sharing

* feat(share): add archive preview

* fix(share): fix some bugs

* feat(openlist_share): add openlist share driver

* fix(share): lack unwrap when get virtual path

* fix: use unwrapPath instead of path for virtual file name comparison

* fix(share): change request method of /api/share/list from GET to Any

* fix(share): path traversal vulnerability in sharing path check

* 修复分享alias驱动的文件 没开代理时无法获取URL

* fix(sharing): update error message for sharing root link extraction

---------

Co-authored-by: Suyunmeng <69945917+Suyunmeng@users.noreply.github.com>
Co-authored-by: j2rong4cn <j2rong@qq.com>
2025-08-19 15:10:02 +08:00
MadDogOwner 5d8bd258c0 refactor(docker): reduce docker image size (#1091)
* fix(docker): reduce image size

* refactor(docker): update user and group creation

* Update Dockerfile

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

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-19 10:27:33 +08:00
huancun _- 08c5283c8c feat(docker): Update docker-compose configuration (#1081)
* feat(docker): Update docker-compose configuration

* Update docker-compose.yml

Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
Signed-off-by: huancun _- <huancun@hc26.org>

---------

Signed-off-by: huancun _- <huancun@hc26.org>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2025-08-18 14:29:59 +08:00
我怎么就不是一只猫呢? 10a14f10cd fix(docker): improve startup process and SIGTERM handling (#1089)
* fix(ci): Modify the way of star OpenList.

* fix(ci): start runsvdir
2025-08-18 11:13:05 +08:00
j2rong4cn f86ebc52a0 refactor(123_open): improve upload (#1076)
* refactor(123_open): improve upload

* optimize buffer initialization for multipart form

* 每次重试生成新的表单

* .
2025-08-17 14:25:23 +08:00
j2rong4cn 016ed90efa feat(stream): fast buffer freeing for large cache (#1053)
Signed-off-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-16 17:19:52 +08:00
tuthanika d76407b201 fix(dropbox): incorrect path error during upload (#1052)
* Fix incorrect path error during upload on Dropbox

* Add RootNamespaceId to the config for direct modification

* Refactor Dropbox header logic: extract JSON marshaling into helper method

* Fix Dropbox: replace marshalToJSONString with utils.Json.MarshalToString
2025-08-16 14:18:02 +08:00
yuyamionini 5de6b660f2 fix(terabox): user not exists error (#1056)
* fix user location error when upload file
2025-08-15 21:25:57 +08:00
Suyunjing 71ada3b656 fix(ci-sync): fix workflow for syncing Repository (#1062) 2025-08-15 18:48:55 +08:00
Suyunjing dc42f0e226 [skip ci]fix(ci): update sync workflow (#1061) 2025-08-15 18:36:52 +08:00
Suyunjing 74bf9f6467 [skip ci]feat(sync): add workflow to sync GitHub repository (#1060)
feat(sync): add workflow to sync GitHub repository to Gitee
2025-08-15 18:12:29 +08:00
我怎么就不是一只猫呢? d0c22a1ecb feat(ci): add the default user for docker image (#1036)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-12 09:51:40 +08:00
j2rong4cn 57fceabcf4 perf(stream): improve file stream range reading and caching mechanism (#1001)
* perf(stream): improve file stream range reading and caching mechanism

* 。

* add bytes_test.go

* fix(stream): handle EOF and buffer reading more gracefully

* 注释

* refactor: update CacheFullAndWriter to accept pointer for UpdateProgress

* update tests

* Update drivers/google_drive/util.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>

* 更优雅的克隆Link

* 修复stream已缓存但无法重复读取

* 将Bytes类型重命名为Reader

* 修复栈溢出

* update tests

---------

Signed-off-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-11 23:41:22 +08:00
MadDogOwner 8c244a984d refactor(assets): migrate to resource domain (#975)
* refactor(assets): migrate to resource domain

* feat(bootstrap): add migration value for logo and favicon settings
2025-08-10 09:57:33 +08:00
火星大王 df479ba806 fix(aliyundrive_open): limit rate for every request (close #724) (#1011)
* fix(aliyundrive_open): limit rate for `Remove` and `MakeDir`; reduce limit for `List` and `Link` (close #724)

* Update drivers/aliyundrive_open/driver.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: 火星大王 <34576789+huoxingdawang@users.noreply.github.com>

* Update drivers/aliyundrive_open/driver.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: 火星大王 <34576789+huoxingdawang@users.noreply.github.com>

* fix(aliyundrive_open): limit rate for every request

* fix(aliyundrive_open): fix limiter not work on reference driver

* fix(aliyundrive_open): typo

* fix(aliyundrive_open): limiter not set to nil after free

* fix(aliyundrive_share): limit rate for every request

---------

Signed-off-by: 火星大王 <34576789+huoxingdawang@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-10 09:55:20 +08:00
MadDogOwner 5ae8e96237 feat(123_open): update Put method to return model.Obj (#1008)
* feat(123_open): update Put method to return model.Obj

* fix(123_open): declear time zones

* chore(123_open): fix typo

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

* fix(123_open): use fixed timezone

* fix(123_open): implement PutResult interface for Open123 driver

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Suyunmeng <69945917+Suyunmeng@users.noreply.github.com>
2025-08-09 15:09:12 +08:00
Suyunjing aa0ced47b0 fix(webdav): Handle HEAD requests for directories with appropriate headers (#1015)
Implement handling of HEAD requests for directories by setting the correct Content-Type and Content-Length headers.
2025-08-09 13:57:09 +08:00
Suyunjing ab747d9052 feat(config): Add PWA manifest.json endpoint for web app installation (#990)
* feat(config): Add PWA manifest.json endpoint for web app installation

* fix: Update comment to English in manifest handler

* fix: fix EOL

* fix: Remove unused fmt import from manifest handler

* feat: use site settings for manifest name and icon

* fix(manifest): Move manifest.json route to static handler for proper CDN handling

* feat: move manifest.json handler to static package and improve path handling

* feat: Add custom static file handler to prevent manifest.json conflicts

* fix: Integrate manifest.json handling into static file serving routes

* fix: Simplify PWA manifest scope handling and static file serving

- Remove CDN-specific logic for PWA manifest scope and start_url
- Always use base path for PWA scope regardless of CDN configuration
- Replace manual file serving logic with http.FileServer for static assets

* fix: Ensure consistent base path handling in site configuration and manifest path construction

* fix: Refactor trailing slash handling in site configuration

* feat(static): update manifest path handling and add route for manifest.json
2025-08-08 20:07:51 +08:00
LmanTW 93c06213d4 feat(local): add directory size support (#624)
* feat(local): add directory size support

* fix(local): fix and improve directory size calculation

* style(local): fix code style

* style(local): fix code style

* style(local): fix code style

* fix(local): refresh directory size when force refresh

Signed-off-by: 我怎么就不是一只猫呢? <26274059+dezhishen@users.noreply.github.com>

* fix:(local): Avoid traversing the parent's parent, which leads to an endless loop

Signed-off-by: 我怎么就不是一只猫呢? <26274059+dezhishen@users.noreply.github.com>

* fix(local:) refresh dir size only enabled

Signed-off-by: 我怎么就不是一只猫呢? <26274059+dezhishen@users.noreply.github.com>

* fix(local): logical error && add RecalculateDirSize && cleaner code for int64

* feat(local): add Benchmark for CalculateDirSize

* refactor(local): 优化移动中对于错误的判断。

---------

Signed-off-by: 我怎么就不是一只猫呢? <26274059+dezhishen@users.noreply.github.com>
Co-authored-by: 我怎么就不是一只猫呢? <26274059+dezhishen@users.noreply.github.com>
2025-08-08 16:59:16 +08:00
Suyunjing b9b8eed285 [skip ci]feat(ci): add FRONTEND_REPO variable to workflows and build script (#1006) 2025-08-08 16:36:22 +08:00
j2rong4cn 317d190b77 fix(ftp): create a new connection for each download (#989) 2025-08-06 20:35:01 +08:00
Sakana 52d7d819ad feat(lenovonas_share): add thumb (#986) 2025-08-06 17:34:43 +08:00
RedSTAR.Cheng 0483e0f868 feat(driver_strm): also shown some files with strm (#969)
* feat(driver_strm): Also shown some files with strm

Allow user set some file types that need to shown with strm, usually subtitles

Most of code was copy and managed from drivers/alias

* 优化

* 优化

* 。

* 添加注释

---------

Co-authored-by: j2rong4cn <j2rong@qq.com>
Co-authored-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
2025-08-06 15:40:48 +08:00
MadDogOwner 08dae4f55f feat(123_open): update upload api v2 (#976) 2025-08-06 15:27:13 +08:00
j2rong4cn 9ac0484bc0 perf(ftp): improve concurrent Link response; fix alias/local driver issues (#974) 2025-08-06 13:32:37 +08:00
j2rong4cn 8cf15183a0 perf: optimize upload (#554)
* pref(115,123): optimize upload

* chore

* aliyun_open, google_drive

* fix bug

* chore

* cloudreve, cloudreve_v4, onedrive, onedrive_app

* chore(conf): add `max_buffer_limit` option

* 123pan multithread upload

* doubao

* google_drive

* chore

* chore

* chore: 计算分片数量的代码

* MaxBufferLimit自动挡

* MaxBufferLimit自动挡

* 189pc

* errorgroup添加Lifecycle

* 查缺补漏

* Conf.MaxBufferLimit单位为MB

* 。

---------

Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2025-08-05 21:42:54 +08:00
MadDogOwner c8f2aaaa55 feat(cmd): add delete command for storage (#952) 2025-08-04 17:30:43 +08:00
j2rong4cn 1208bd0a83 fix(fs): nil interface not equal to nil (#971)
https://go.dev/doc/faq#nil_error
2025-08-03 23:51:11 +08:00
j2rong4cn 6b096bcad4 fix(fs): deadlock when get link error (#963) 2025-08-02 17:49:53 +08:00
Seven 58dbf088f9 fix(fs): forget cache when get link error (#956) 2025-08-02 11:03:34 +08:00
Seven 05ff7908f2 fix(strm): encoded path is ineffective (#951) 2025-08-02 00:23:18 +08:00
Suyunjing a703b736c9 feat(offline_download): filter empty URLs in offline download requests (#948) 2025-08-01 16:12:21 +08:00
MadDogOwner e458f2ab53 fix(bootstrap): add newline after initial admin password output (#943)
fix(bootstrap): add newline after initial admin  password output
2025-08-01 13:43:41 +08:00
Rambin a5a22e7085 fix(local): Treat junction as directory in Windows. (#809)
Treat junction as directory in Windows.
2025-07-31 13:54:56 +08:00
hshpy 9469c95b14 fix(security): potential XSS vulnerabilities (#896) 2025-07-31 12:57:20 +08:00
MadDogOwner cf912dcf7a fix(cmd): output to console (#920)
fix(cmd): output to terminal
2025-07-31 11:44:00 +08:00
MadDogOwner ccd4af26e5 feat(patch): add migration from Alist V3 driver to OpenList (#919)
* feat(patch): add migration from Alist V3 driver to OpenList

* chore(patch): improve logging
2025-07-31 11:43:21 +08:00
hcrgm 1682e873d6 feat(search): enhanced meilisearch search experience (#864)
* feat(search): enhanced `meilisearch` search experience
- upgrade `meilisearch` dependency
- support subdirectory search
- optimize searchDocument fields for subdirectory search
- specify full index uid instead of index prefix

* fix(search): more fixes to `meilisearch`
- make use of context where context was not used
- remove code of waiting task in deletion process, as tasks are queued and will be executed orderly (if tasks were submitted to the queue successfully), which can improve `AutoUpdate` performance
2025-07-31 11:24:22 +08:00
Seven 54ae7e6d9b feat(115_open): Add GetObjInfo to accelerate getting link (#888)
* feat(115_open): Add GetObjInfo to accelerate getting link

* feat(fs): use cache directly when cache exist
2025-07-31 11:20:02 +08:00
Seven 991da7d87f feat(strm): add local mode (#885)
* feat(strm): add local mode

* Update drivers/strm/meta.go

Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
Signed-off-by: Seven <53081179+Seven66677731@users.noreply.github.com>

* feat(strm): local mode add sign

---------

Signed-off-by: Seven <53081179+Seven66677731@users.noreply.github.com>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2025-07-31 11:18:59 +08:00
Dgs a498091aef fix(123&&123_share): fix link request header referer (#915) 2025-07-31 10:10:38 +08:00
MadDogOwner 976c82bb2b fix(drivers): update time-related fields to int64 (#913)
- In doubao/types.go:
  - Change LastUpdateTime from int to int64
  - Change UserCreateTime from int to int64
- In doubao_share/types.go:
  - Change CreateTime and UpdateTime from int to int64 in ShareInfo and FilePath
- In quark_uc/types.go:
  - Change UpdateTime from int to int64 in TranscodingResp

These changes ensure consistent and accurate representation of timestamp data across the project.
2025-07-31 10:10:32 +08:00
Suyunjing 5b41a3bdff feat(ci): Add support for LoongArch64 architecture builds (#907) 2025-07-31 10:10:19 +08:00
Suyunjing 19d1a3b785 refactor(ci): Refactor Docker build to use base images and dynamic Dockerfile generation (#904) 2025-07-30 15:04:29 +08:00
Suyunjing 3c7b0c4999 fix(qb): Configure HTTP client with connection pooling and fix resource leaks in qBittorrent client. (#898) 2025-07-29 21:56:36 +08:00
ILoveScratch d6867b4ab6 fix(user): show admin password on first start (#883)
* fix: fix admin password not shown in first start
* chore: add time dependence

Co-authored-by: Yinan Qin <39023210+elysia-best@users.noreply.github.com>
Signed-off-by: ILoveScratch <ilovescratch@foxmail.com>

* fix: fix log format

Co-authored-by: Yinan Qin <39023210+elysia-best@users.noreply.github.com>
Signed-off-by: ILoveScratch <ilovescratch@foxmail.com>

---------

Signed-off-by: ILoveScratch <ilovescratch@foxmail.com>
Co-authored-by: Yinan Qin <39023210+elysia-best@users.noreply.github.com>
2025-07-29 21:36:27 +08:00
hshpy 11cf561307 fix(security): potential XSS vulnerabilities (#880)
* fix(security): potential XSS vulnerabilities

* chore: replace alist identifier to openlist identifier

Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
Signed-off-by: ILoveScratch <ilovescratch@foxmail.com>

---------

Signed-off-by: ILoveScratch <ilovescratch@foxmail.com>
Co-authored-by: ILoveScratch <ilovescratch@foxmail.com>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2025-07-29 20:17:11 +08:00
Suyunjing 239b58f63e fix(ci):Disable linux/s390x Docker builds (#887) 2025-07-29 16:22:50 +08:00
MadDogOwner 7da06655cb feat(setting): add site version information (#859)
* feat(setting): add site version information

* feat(conf): update conf.WebVersion to rolling

* fix(static): update condition to check conf.Version instead of conf.WebVersion

* fix(build.sh): use rolling release for web frontend in dev and beta builds

* chore(build.sh): update GitAuthor to The OpenList Projects Contributors

* fix(static): update condition to check conf.WebVersion
2025-07-29 09:49:33 +08:00
花月喵梦 e0b3a611ba feat(thunderx,pikpak): add offline download support for ThunderX; add ctx to specific PikPak functions (#879)
* feat(thunderx,pikpak): add offline download support for ThunderX; add ctx to specific PikPak functions

* Update internal/offline_download/tool/download.go

Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
Signed-off-by: 花月喵梦 <152958106+nekohy@users.noreply.github.com>

---------

Signed-off-by: 花月喵梦 <152958106+nekohy@users.noreply.github.com>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2025-07-29 09:46:28 +08:00
Suyunjing be1ad08a83 feat(ci):Add Windows 7 and LoongArch Release build support (#857)
* feat:Add Windows 7 and LoongArch old world build support (#30)

* feat:Add Windows 7 and Loongson old world build support

- Add BuildWin7() function with patched Go compiler for Windows 7 compatibility
- Add BuildLoongOldWorld() function for linux-loong64-abi1.0 target
- Create Zig-based wrapper scripts for Windows 7 cross-compilation
- Integrate new build functions into existing release workflows

* fix(win7):Add MinGW-w64 toolchain and improve LoongArch ABI isolation

- Install MinGW-w64 cross-compilation toolchain for Win7 compatibility
- Replace Zig compiler wrappers with MinGW-w64 for Windows 7 builds
- Add Go build cache cleaning to prevent LoongArch ABI1.0/ABI2.0 cross-contamination
- Force clean rebuilds (-a flag) for LoongArch builds to ensure ABI compatibility

* feat: add Windows 7 build support to beta release workflow

* feat: add LoongArch ABI2.0 support alongside existing ABI1.0 build (#31)

- Add BuildWin7() function with patched Go compiler for Windows 7 compatibility
- Add BuildLoongOldWorld() function for linux-loong64-abi1.0 target
- Create Zig-based wrapper scripts for Windows 7 cross-compilation
- Integrate new build functions into existing release workflows
- Install MinGW-w64 cross-compilation toolchain for Win7 compatibility
- Replace Zig compiler wrappers with MinGW-w64 for Windows 7 builds
- Add Go build cache cleaning to prevent LoongArch ABI1.0/ABI2.0 cross-contamination
- Force clean rebuilds (-a flag) for LoongArch builds to ensure ABI compatibility

* [skip ci]refactor:Refactor LoongArch builds to separate glibc from musl compilation

* fix(go-cache):Improve error handling for Go module cache cleaning in LoongArch builds

* feat(build): Enhance LoongArch build process with improved toolchain setup and cache management

* fix(build): Update Windows 7 target naming in build scripts and workflows

* refactor(build): Replace MinGW-w64 with Zig for Windows 7 toolchain in build scripts

* chore(cgo): remove cgo-actions subproject
2025-07-27 00:27:31 +08:00
j2rong4cn 4e9c30f49d feat(fs): full support webdav cross-driver copy and move (#823)
* fix(fs): restore webdav cross-driver copy and move

* fix bug

* webdav支持复制、移动 文件夹

* 优化

* 。
2025-07-26 00:27:46 +08:00
j2rong4cn 0ee31a3f36 fix(crypt): wrong ContentLength 2025-07-25 19:55:22 +08:00
MadDogOwner 23bddf991e feat(drivers): enable local sorting for cloudreve, ilanzou (#840)
* feat(cloudreve): enable local sorting

* feat(ilanzou): enable local sorting
2025-07-25 18:01:19 +08:00
MadDogOwner da8d6607cf fix(static): support logo replacement (#834 Close #754) 2025-07-25 17:12:51 +08:00
hshpy 6134574dac fix(fs): rename bug (#832)
* fix(fs): rename bug

* chore

* fix bug

* .

---------

Co-authored-by: j2rong4cn <j2rong@qq.com>
2025-07-25 13:42:39 +08:00
Ljcbaby b273232f87 refactor(log): redir utils.Log to logrus after init (#833) 2025-07-25 13:38:45 +08:00
Ljcbaby 358e4d851e refactor(log): filter (#816) 2025-07-25 11:33:27 +08:00
Suyunmeng e8a1ed638a fix(ci):Exclude FreeBSD patch releases from version detection 2025-07-24 22:41:45 +08:00
MadDogOwner 4106e2a996 fix(static): correct CDN fetch condition for index.html (#814) 2025-07-24 22:28:58 +08:00
Yinan Qin c2271df64e fix(ci): update OpenListTeam/cgo-actions to v1.2.2 to fix loongarch64 build (#811)
* Update beta_release.yml

* Update build.yml
2025-07-24 22:20:23 +08:00
huancun _- d4b8570eb8 fix(docker): Fix the runsvdir permission issue caused by su-exec user switching and resolve the RUN_ARIA2 variable compatibility problem. (#805) 2025-07-24 17:22:49 +08:00
renovate[bot] bd297e8ccc fix(deps): update module golang.org/x/image to v0.29.0 (#804)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-24 16:22:19 +08:00
renovate[bot] 923d282c8a fix(deps): update module github.com/sheltonzhu/115driver to v1.1.0 (#803)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-24 16:21:32 +08:00
renovate[bot] 4d8c4d7089 fix(deps): update module github.com/coreos/go-oidc to v2.3.0+incompatible (#586)
* fix(deps): update module github.com/coreos/go-oidc to v2.3.0+incompatible

* Update go.mod

Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>

---------

Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2025-07-24 16:21:03 +08:00
Seven e93ab76036 feat(task-group): introduce TaskGroupCoordinator for coordinated task execution (#721)
* feat(task): add task hook,batch task
refactor(move): move use CopyTask

* Update internal/task/batch_task/refresh.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Seven <53081179+Seven66677731@users.noreply.github.com>

* fix: upload task allFinish judge

* Update internal/task/batch_task/refresh.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Seven <53081179+Seven66677731@users.noreply.github.com>

* feat: enhance concurrency safety

* 优化代码

* 解压缩

* 修复死锁

* refactor(move): move as task

* 重构,优化

* .

* 优化,修复bug

* .

* 修复bug

* feat: add task retry judge

* 代理Task.SetState函数来判断Task的生命周期

* chore: use OnSucceeded、OnFailed、OnBeforeRetry functions

* 优化

* 优化,去除重复代码

* .

* 优化

* .

* webdav

* Revert "fix(fs):After the file is copied or moved, flush the cache of the directory that was copied or moved to."

This reverts commit 5f03edd683.

---------

Signed-off-by: Seven <53081179+Seven66677731@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: j2rong4cn <j2rong@qq.com>
2025-07-24 16:15:24 +08:00
Suyunjing a9f02ecdac refactor(log):Refactor log filtering to use centralized configuration and add server-specific filtering (#798)
* feat(log):Add configurable log filtering middleware for HTTP requests

Implement a comprehensive log filtering system that allows selective suppression of HTTP request logs based on paths, methods, and prefixes. The system includes environment variable configuration support and filters health checks, WebDAV requests, and HEAD requests by default to reduce log noise.

* fix(log):Replace gin.DefaultLogFormatter with custom implementation

* Remove filtered logger test file

* fix(log):Refactor log filtering to use centralized configuration and add server-specific filtering

* fix(log):Add documentation comments for log filtering configuration
2025-07-24 16:10:47 +08:00
renovate[bot] 93849a3b5b fix(deps): update module github.com/pquerna/otp to v1.5.0 (#799)
Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2025-07-24 16:07:23 +08:00
renovate[bot] c2e0d0c9ce fix(deps): update module github.com/protonmail/go-crypto to v1.3.0 (#800)
Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2025-07-24 16:06:50 +08:00
renovate[bot] 4a713363ee fix(deps): update module github.com/azure/azure-sdk-for-go/sdk/storage/azblob to v1.6.2 (#801)
Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2025-07-24 16:06:10 +08:00
renovate[bot] 3da8ccb7a7 fix(deps): update module github.com/rclone/rclone to v1.70.3 (#802)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-24 16:05:20 +08:00
renovate[bot] 676b8cff0b fix(deps): update azure-sdk-for-go monorepo (#579)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-24 10:27:36 +08:00
renovate[bot] 57cf28fc90 fix(deps): update github.com/fclairamb/ftpserverlib digest to 4a925d7 (#675)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-24 10:26:39 +08:00
renovate[bot] 8cf90e074d fix(deps): update module github.com/charmbracelet/bubbletea to v1.3.6 (#585)
Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2025-07-24 10:26:23 +08:00
renovate[bot] 74c2ed8306 fix(deps): update module github.com/charmbracelet/bubbles to v0.21.0 (#583)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-24 10:25:09 +08:00
Suyunjing 5f03edd683 fix(fs):After the file is copied or moved, flush the cache of the directory that was copied or moved to. (#592)
* fix(fs):After the file is copied, the cache of the copied directory is refreshed

* fixed randomstring

* fixed EOL and Sync branch

chore(quark_uc): `webdav_policy` default to native_proxy

* fixed uuid and other bugs

* fixed comments

* fixed EOL

* add move refresh

* fixed builds

* fixed batch

* change betch to task.go

---------

Co-authored-by: Sumengjing <146963948+suyunjing-su@users.noreply.github.com>
2025-07-24 10:24:12 +08:00
hshpy 8b65c918d4 chore(permission): admin enables webdav read-only by default (#726)
chore: admin enables webdav read-only by default
2025-07-24 10:19:49 +08:00
renovate[bot] b5f0e3e5ee fix(deps): update module github.com/go-webauthn/webauthn to v0.13.4 (#677)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-24 10:05:44 +08:00
renovate[bot] 179894ff37 fix(deps): update module github.com/ipfs/go-cid to v0.5.0 (#680)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-24 10:05:05 +08:00
renovate[bot] e2fc89c637 chore(deps): update dependency go to v1.24.5 (#783)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-24 10:04:20 +08:00
renovate[bot] cacf67b181 fix(deps): update module github.com/yuin/goldmark to v1.7.13 (#794)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-24 10:04:00 +08:00
huancun _- afb043e1d6 feat(docker): Change keep-alive strategy to runit, add aria2 log support (#791) 2025-07-24 09:19:33 +08:00
Suyunjing d9debb81ad feat(log):Add configurable log filtering middleware for HTTP requests (#782)
* feat(log):Add configurable log filtering middleware for HTTP requests

Implement a comprehensive log filtering system that allows selective suppression of HTTP request logs based on paths, methods, and prefixes. The system includes environment variable configuration support and filters health checks, WebDAV requests, and HEAD requests by default to reduce log noise.
2025-07-24 00:00:26 +08:00
yuyamionini 4c069fddd6 fix(terabox): file upload error (#733)
* fix(terabox):fix file upload error failed to create file errno 10

Signed-off-by: yuyamionini <46483865+yuyamionini@users.noreply.github.com>

* fix(terabox):fix file upload error failed to create file errno 10

Signed-off-by: yuyamionini <46483865+yuyamionini@users.noreply.github.com>

* replace the goto statement with the retry-go package

Signed-off-by: yuyamionini <46483865+yuyamionini@users.noreply.github.com>

* Update util.go

Signed-off-by: yuyamionini <46483865+yuyamionini@users.noreply.github.com>

* Update util.go

Signed-off-by: yuyamionini <46483865+yuyamionini@users.noreply.github.com>

* go fmt

---------

Signed-off-by: yuyamionini <46483865+yuyamionini@users.noreply.github.com>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2025-07-23 23:42:12 +08:00
MadDogOwner b450a2104d chore(docs): update domain (#788)
* chore(docs): update domain

* docs(issue): add guide link for bug reporting
2025-07-23 14:26:21 +08:00
MadDogOwner 7d0de17daf feat(static): fetch index.html from cdn for beta (#372)
* refactor(static): simplify folder iteration in Static function

* feat(static): disable local static when `cdn` is set

* feat(static): fetch index.html from cdn for beta

* refactor(static): use RestyClient for better retrying

* fix(static): add Accept header when fetching index.html from CDN

* refactor(static): optimize HTML replacement

* chore(static): add logging to static file system initialization

* feat(static): ensure static file redirected to CDN
2025-07-22 22:14:07 +08:00
hshpy bba4fb2203 fix(security): directory traversal (#744)
* fix(security): Directory traversal

* chore: .

* 优化

---------

Co-authored-by: j2rong4cn <j2rong@qq.com>
2025-07-22 14:45:01 +08:00
j2rong4cn a20c2020f8 fix(cmd): optimize parse of command flag --data (#777)
* Fix (cmd): optimize parse of command flag `--data`

* DBFile

* 优化

* os.Getwd()
2025-07-22 10:51:28 +08:00
MadDogOwner a92b5eb929 refactor(cloudreve): use retry-go for net/http uploads (#773)
* refactor(cloudreve): use retry-go for uploads

* refactor(cloudreve_v4): use retry-go for uploads

* refactor(onedrive): use retry-go for uploads

* refactor(onedrive_app): use retry-go for uploads

* chore(onedrive_app): remove unnecessary error handling for host retrieval

* feat(cloudreve): move read logic inside retry block

* feat(cloudreve_v4): move read logic inside retry block

* feat(onedrive): move read logic inside retry block

* feat(onedrive_app): move read logic inside retry block
2025-07-22 10:25:04 +08:00
Yinan Qin 6817494a41 chore(ci): update cgo-actions to 1.2.1 & add patch version define for go (#779)
chore(ci): update cgo-actions to 1.2.1 & fix patch version for go
2025-07-22 09:02:07 +08:00
SenkjM 5a0d8ee1b8 feat(proxy): add disable proxy sign (#764)
* feat(proxy): add disable proxy sign

* Update driver.go

* GenerateDownProxyUrl

* .

* Update internal/op/driver.go

Signed-off-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>

* .

---------

Signed-off-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
Co-authored-by: j2rong4cn <j2rong@qq.com>
Co-authored-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
2025-07-21 17:03:08 +08:00
MadDogOwner 012e51c551 fix(cloudreve_v4): remove deprecated authn check for login (#767)
* fix(cloudreve_v4): disable authn check for login

* chore(cloudreve_v4): update site login config fields
2025-07-21 15:53:10 +08:00
Sakana 59ec1dbc9b feat(lenovonas_share): add option to not show root directory (#772) 2025-07-21 14:38:10 +08:00
j2rong4cn 6bb28d13f9 fix(quark): set the transcoding link ContentLength to the correct size 2025-07-20 16:40:32 +08:00
Xi Xu 811a862288 feat(archives): add additional accepted archive extensions (#747) 2025-07-20 15:32:46 +08:00
j2rong4cn 74d32fd4d7 fix(simplehttp): logic bug when unable to parse file name (#761) 2025-07-20 14:13:30 +08:00
j2rong4cn cedb3d488d [skip ci] chore(ci): output binary name set to openlist 2025-07-19 23:02:29 +08:00
pnparadise 86324d2d6b fix(net): ensure accurate content-length in response (#749)
* fix(fs): ensure accurate content-length in http2 requests

Chrome browsers were unable to preview thumbnails, reporting an
'ERR_HTTP_2_PROTOCOL_ERROR'. This was caused by an incorrect
content-length header in the server's response for thumbnail images.

This commit corrects the content-length calculation, allowing
Chrome and other compliant clients to render thumbnails correctly.

* fix(net): ensure accurate content-length in response

* 补缺

* .

---------

Co-authored-by: zhiqiang.huang <zhiqiang.tech@gmail.com>
Co-authored-by: j2rong4cn <j2rong@qq.com>
2025-07-19 20:36:27 +08:00
Pikachu Ren 648079ae24 remove upx (#750)
Update build.sh

Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2025-07-18 12:38:17 +08:00
Dgs e8d45398d6 feat(quark_uc_tv): add streaming link api (#728) 2025-07-17 14:24:16 +08:00
j2rong4cn 0c461991f9 chore: standardize context keys with custom ContextKey type (#697)
* chore: standardize context keys with custom ContextKey type

* fix bug

* 使用Request.Context
2025-07-14 23:55:17 +08:00
j2rong4cn 2a4c546a8b feat: default settings api (#716)
* feat: default settings api

* fix logic bug

* chore
2025-07-14 23:41:34 +08:00
SenkjM 750d4eb3f6 docs(README): add disclaimer (#705)
add disclaimer
2025-07-13 15:22:25 +08:00
j2rong4cn cc01b410a4 perf(link): optimize concurrent response (#641)
* fix(crypt): bug caused by link cache

* perf(crypt,mega,halalcloud,quark,uc): optimize concurrent response link

* chore: 删除无用代码

* ftp

* 修复bug;资源释放

* 添加SyncClosers

* local,sftp,smb

* 重构,优化,增强

* Update internal/stream/util.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>

* chore

* chore

* 优化,修复bug

* .

---------

Signed-off-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-12 17:57:54 +08:00
itsHenry e5fbe72581 fix(security): add login count validation for webdav (#693) 2025-07-12 17:03:41 +08:00
Suyunmeng 283f3723d1 [skip ci] chore(ci): update openwrt hook 2025-07-12 12:06:36 +08:00
Suyunmeng ad8c7b37a1 chore(ci):Disable duplicate build process 2025-07-12 11:49:27 +08:00
Suyunjing a84ffb96e9 chore(ci):Simplify the build process (#686)
* refactor(ci):Minify build files
2025-07-11 20:30:31 +08:00
Seven 19c6b6f930 feat(115_open): add offline download (#683) 2025-07-11 20:17:54 +08:00
renovate[bot] eed3c0533c fix(deps): update module github.com/go-resty/resty/v2 to v2.16.5 (#628)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-11 10:26:44 +08:00
renovate[bot] c72ba9828a fix(deps): update module github.com/deckarep/golang-set/v2 to v2.8.0 (#589)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-11 10:25:08 +08:00
renovate[bot] 4965a1b909 fix(deps): update module github.com/blevesearch/bleve/v2 to v2.5.2 (#582)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-11 10:24:50 +08:00
renovate[bot] 1bba550469 chore(deps): update dependency go to 1.24 (#578)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-11 10:24:23 +08:00
renovate[bot] d678322b18 fix(deps): update module github.com/yuin/goldmark to v1.7.12 (#575)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-11 10:24:09 +08:00
renovate[bot] efd8897bdf fix(deps): update module github.com/pkg/sftp to v1.13.9 (#574)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-11 10:23:52 +08:00
MadDogOwner 7c7cec0993 style(offline_download): add more description in log (#653)
fix(offline_download): add more description in log
2025-07-09 14:16:05 +08:00
Seven 3838ef0663 feat(traffic): update progress when caching file (#646)
* feat(traffic): update progress when caching file

* 调整参数位置和命名

---------

Co-authored-by: j2rong4cn <j2rong@qq.com>
2025-07-08 21:41:45 +08:00
Seven 9e610af114 fix(115_open): upload progress error (#637) 2025-07-07 18:39:09 +08:00
j2rong4cn 0177177238 fix(crypt): pass refresh list request (close #609) 2025-07-06 13:20:42 +08:00
Suyunjing a77e515c9b fix(ocr): repair verification code OCR recognition service (#602)
* fix(ocr):Repair verification code OCR recognition service

* 修复对 非新用户 无效的问题

* chore: SettingItem.PreDefault重命名为MigrationValue

---------

Co-authored-by: j2rong4cn <j2rong@qq.com>
2025-07-06 13:09:17 +08:00
ILoveScratch 4af16ab009 fix(115open):fix limit_rate save (#601) 2025-07-06 12:07:07 +08:00
j2rong4cn da35423198 [skip ci] chore: go mod tidy 2025-07-06 00:55:23 +08:00
j2rong4cn 9612d61e60 chore(pkg): update singleflight 2025-07-05 13:31:47 +08:00
j2rong4cn 92f396df10 chore(quark_uc): webdav_policy default to native_proxy 2025-07-04 19:06:40 +08:00
j2rong4cn 9557834342 [skip ci] chore(net): update test 2025-07-04 18:44:52 +08:00
Seven 288ba2fcda chore(strm): remove excess parameters (#587) 2025-07-04 17:50:37 +08:00
j2rong4cn f3920b02f7 fix(net): goroutine deadlock 2025-07-04 12:52:21 +08:00
renovate[bot] 2ec9dad3db fix(deps): update module github.com/charmbracelet/lipgloss to v0.13.1 (#449)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 12:16:42 +08:00
renovate[bot] e11227fe2d fix(deps): update module github.com/otiai10/copy to v1.14.1 (#530)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 12:16:25 +08:00
renovate[bot] 859931b78c fix(deps): update module github.com/nwaples/rardecode/v2 to v2.1.1 (#529)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 11:27:14 +08:00
renovate[bot] b591524ac3 fix(deps): update module github.com/dlclark/regexp2 to v1.11.5 (#450)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 11:26:53 +08:00
renovate[bot] dc26b4fce5 fix(deps): update module github.com/aws/aws-sdk-go to v1.55.7 (#439)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 11:26:36 +08:00
renovate[bot] f8cf02a2da fix(deps): update module github.com/golang-jwt/jwt/v4 to v4.5.2 (#453)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 11:26:11 +08:00
renovate[bot] a214e794f4 fix(deps): update module github.com/ncw/swift/v2 to v2.0.4 (#525)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 11:25:52 +08:00
renovate[bot] 54d761b371 fix(deps): update module github.com/gin-contrib/cors to v1.7.6 (#451)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 11:20:51 +08:00
yonzilch bea7a9b0e4 chore: remove deprecated trainbit drive (#563)
* chore: remove deprecated trainbit drive

* chore: go mod tidy

---------

Co-authored-by: j2rong4cn <j2rong@qq.com>
2025-07-03 18:30:37 +08:00
ShenLin a46f4cff18 chore(pr auto reply ci): Update PR title validation and feedback messages (#559)
Update PR title validation and feedback messages

Improves the PR title regex to be non-greedy and adds 'chore' to the allowed prefixes. Enhances feedback comments with clearer instructions in both Chinese and English, including guidance for PRs spanning multiple components.
2025-07-03 15:33:02 +08:00
ShenLin 8eb2d600c7 chore(issues): issue and pr auto reply (#551) 2025-07-03 13:11:39 +08:00
j2rong4cn ffb6c2a180 refactor: optimize stream, link, and resource management (#486)
* refactor: optimize stream, link, and resource management

* Link.MFile改为io.ReadSeeker类型

* fix (crypt): read on closed response body

* chore

* chore

* chore
2025-07-03 10:39:34 +08:00
j2rong4cn 8e19a0fb07 fix(s3): logic bug (close #547 #548) 2025-07-03 10:36:34 +08:00
hshpy 79f4f96217 feat(strm):add sign and encode path options (#537) 2025-07-02 21:09:57 +08:00
j2rong4cn 7f53390dce fix(build): version lost 2025-07-02 21:00:43 +08:00
j2rong4cn e83f8e197a feat(offline-download): SimpleHttp: download stream direct upload (#523)
* feat(offline-download): stream download to upload

* 重命名stream_put为upload_download_stream

* chore
2025-07-02 18:47:16 +08:00
j2rong4cn d707f002eb chore(quark_uc): WebProxy enabled by default 2025-07-02 16:37:56 +08:00
renovate[bot] c0f69f7fa7 fix(deps): update module github.com/bodgit/sevenzip to v1.6.1 (#448)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-02 15:36:31 +08:00
renovate[bot] adf914115f fix(deps): update module github.com/mholt/archives to v0.1.3 (#456) 2025-07-02 15:35:13 +08:00
itsHenry c166fe6127 chore: remove exp and go mod tidy (#440) 2025-07-02 15:30:53 +08:00
ILoveScratch 9725e0fd76 fix(s3): correctly handle URL when RemoveBucket is enabled (#497)
* fix(s3): correctly handle URL when RemoveBucket is enabled

* fix(s3): handle errors
2025-07-02 15:23:22 +08:00
hshpy 5c4cd1b198 feat(strm): support multiple drivers (#510) 2025-07-02 15:16:46 +08:00
SenkjM 44f4658f37 docs: better error hint for wrong refresh token (#517)
* docs: better error hint for wrong refresh token

* fix: modify punctuation
2025-07-02 10:20:43 +08:00
j2rong4cn b4997e7a7e Revert "fix(fs): update objs cache" (close #511)
Revert "fix(fs): update objs cache (#507)"

This reverts commit f26892ac3c.
2025-07-01 20:33:44 +08:00
Seven f26892ac3c fix(fs): update objs cache (#507) 2025-07-01 15:46:34 +08:00
ShenLin aae3851979 chore(README): various optimizations, reordering, and corrections (#504) 2025-07-01 15:22:37 +08:00
Seven a17b3dc405 feat(strm_driver): add strm driver (#410)
* feat(strm_driver): add strm driver

* chore(strm_driver): get api_url from context

* 优化代码

* chore(strm_driver): update package name

---------

Co-authored-by: j2rong4cn <j2rong@qq.com>
2025-07-01 14:29:28 +08:00
DearTanker 022614f155 chore(readme style): remove line break to prevent visible underline (#501)
style: Remove the line break of the img tag in readme to avoid GitHub's incorrect rendering of the blue underline

Co-authored-by: ShenLin <773933146@qq.com>
2025-07-01 12:15:28 +08:00
MadDogOwner 874dc292ae fix(gomod): go modules with tagged versions (#499)
fix: go modules with tagged versions
2025-07-01 09:54:50 +08:00
MadDogOwner 9442013b37 feat(cloudreve_v4): enhance metadata and lock conflict handling (#485)
* feat(cloudreve_v4): add metadata constants

* fix(cloudreve_v4): enhance thumbnail handling

* feat(cloudreve_v4): add HideUploading option

* fix(cloudreve_v4): handle lock conflict during file deletion
2025-07-01 01:06:28 +08:00
j2rong4cn 862b1c3c53 chore(net): remove unnecessary goroutine 2025-07-01 00:28:26 +08:00
Suyunjing 52c93f2046 build:Update old dependencies to new hosting (#495)
* build:Update old dependencies to new hosting
2025-06-30 21:26:42 +08:00
Dgs 3d13d5213b feat(quark): add transcoding link api (#470) 2025-06-30 16:20:45 +08:00
j2rong4cn 103abc942e refactor: pass api_url through context (#457)
* refactor: pass `api_url` through context

* 移除 LinkArgs.HttpReq

* pref(alias): 减少不必要下载代理

* 修复bug

* net: 支持1并发 分片下载
2025-06-30 15:48:05 +08:00
Seven f0236522f3 fix(115): error getting file sha1 when upload (#482) 2025-06-30 12:58:49 +08:00
Suyunjing 6a3b8fab06 feat(driver):add online api user-agent (#483) 2025-06-30 10:35:52 +08:00
Suyunmeng 5c288dc763 fixed(ua):fixed openlist ua 2025-06-30 09:15:56 +08:00
j2rong4cn 6d0d3ac612 fix: crypt: file already closed; net: concurrent download deadlock 2025-06-30 01:49:27 +08:00
jenken827 1ec97733e5 fix(crypt cmd): correctly process encrypted folder names and file nam… (#462)
fix(crypt cmd): correctly process encrypted folder names and file name suffix
2025-06-29 22:22:47 +08:00
j2rong4cn ded67b746b fix(115): optimize upload (close #364) 2025-06-29 18:55:57 +08:00
Suyunjing 4590795cba fixed(fs):fixed overwrite functions (#469)
* fixed(fs):fixed overwrite functions
2025-06-29 12:17:23 +08:00
Suyunjing 060fd36883 feat(ci):Add lite version build and standardize Action naming (#464)
* add lite version

* fixed lite ci

* test

* fixed lite version

* fixed release build md5 and tar

* fixed lite

* fixed release ci

* fixed ci secrets

* fixed ci

* fixed ci

* fixed docker ci

* fixed docker ci

* fixed ci

* fixed docker ci

* fixed docker ci

* fixed docker ci

* ci:delete lite in beta version

* feat(ci):Add Lite Version Build

* Fixed Beta version Docker

* Fixed Web Lite

* fixed EOL

* fixed EOL

---------

Co-authored-by: Sumengjing <146963948+suyunjing-su@users.noreply.github.com>
2025-06-28 22:22:16 +08:00
ILoveScratch 76a1f99df1 chore(default setting): add avif in default image settings (#458) 2025-06-28 19:18:08 +08:00
renovate[bot] 38766a4cb7 fix(deps): update github.com/t3rm1n4l/go-mega digest to a19cff0 (#435)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-27 21:31:50 +08:00
renovate[bot] bcc518cf96 fix(deps): update github.com/zzzhr1990/go-common-entity digest to 1a20004 (#436)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-27 21:27:02 +08:00
renovate[bot] 3fdb2c79bf fix(deps): update github.com/fclairamb/ftpserverlib digest to 7accbe1 (#432)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-27 21:17:19 +08:00
itsHenry 18f7a2ba0e fix(s3): fix deleting an empty folder issue and filename encoding (#429) 2025-06-27 20:26:53 +08:00
二丫讲梵 e32cebb153 fix(deps): resolve go.mod tidy failure (#388)
fix: go.mod tidy failed

Co-authored-by: ShenLin <773933146@qq.com>
Co-authored-by: Suyunjing <69945917+Suyunmeng@users.noreply.github.com>
2025-06-27 15:36:50 +08:00
XZB-1248 02031bd835 feat(s3): add Content-Disposition header (#365)
* add(s3): add Content-Disposition header

* Update driver.go

Signed-off-by: XZB-1248 <28593573+XZB-1248@users.noreply.github.com>

* Update driver.go

Signed-off-by: XZB-1248 <28593573+XZB-1248@users.noreply.github.com>

---------

Signed-off-by: XZB-1248 <28593573+XZB-1248@users.noreply.github.com>
Co-authored-by: XZB-1248 <i@1248.ink>
Co-authored-by: Suyunjing <69945917+Suyunmeng@users.noreply.github.com>
2025-06-27 15:29:08 +08:00
ShenLin 7726cb14a0 chore(issue): split Issue templates (#417)
* chore(issue): Update issue templates with improved descriptions and links

Enhanced bug and feature request templates with bilingual descriptions, default titles, and updated documentation links. Added new contact options in config.yml, including a Telegram chat link. Improved clarity and localization for user instructions.

* split

* zh

* test preview

* en

* fix temp preview error

* one line and multiple reproduction links

* fix en

* Revert "fix en"

This reverts commit b3cb48afb4.

* Revert "one line and multiple reproduction links"

This reverts commit cd09ef0d15.

* split fr

* fix temp preview error

* consistency

* fr

* reorder

* split

* fix dup

* consistency

* again due to ai: fix temp preview error

* summary
2025-06-27 15:28:47 +08:00
j2rong4cn 23cfe8090b pref(net): improve concurrent read and write buffer (#416)
* pref(net): improve concurrent read and write buffer

* chore
2025-06-27 15:18:11 +08:00
Dgs d89d0a05b4 feat(189tv): add 189cloudTV driver (#418) 2025-06-27 15:09:12 +08:00
Dgs 14d57ae2ec fix(189pc): fix redirect_url format (#420) 2025-06-27 15:00:09 +08:00
Suyunjing d5f4b687bb fix:fixed ci setup web error (#394)
* chore:fixed setup web

* fix(ci):Fixed Setup Web CI
2025-06-26 13:38:37 +08:00
Dgs bdb880f9f2 feat(quark_open): support rapid upload and thumbnail (#393) 2025-06-26 12:20:05 +08:00
Suyunjing 22575a1c61 chore:Add auto-trigger support for OpenWRT builds (#375)
* Fixed webhook

* change repository

* fixed

* hook repo

* fixed makefile

* change repository name

* Limit to a single warehouse token
2025-06-25 21:24:03 +08:00
Pikachu Ren 890297aa27 add(driver): quark 302 test (#367)
* add(driver): quark 302 test

* del(driver): baidu share

* add(driver): revert quark 302 test
2025-06-25 16:38:37 +08:00
Suyunjing 0fd602bc1b refactor(fs):Refactor the delete function and fix known issues (#353)
* fix(move):Fix file move logic

* fix(move):fixed move logic

* fix(move):Fixed move logic

* Fixed errs

* fix(move):fixed movetask

* fix(move):fix movetask

* fixed

* fix(move):Refactoring the move structure

* fix(move):Fixed move system

* Fixed

* Fixed

* Fixed

* Fixed

* Fixed

* Rollback

* Fixed and Refactor

* fix(move):fixed

* fix(move):Solve related performance issues

* refacter(move):fixed build bugs
2025-06-24 23:36:37 +08:00
Dgs f6470af971 fix(123&123open): repair etag format (#349) 2025-06-24 22:14:11 +08:00
Dgs d695d28e13 feat(thunder&thunder_browser): fix deviceId generation & support offline download and update login interface (#290)
* fix(thunder): fix deviceID generation

* feat(thunder_browser): support offline download and update login interface

* feat(thunder_browser): add fluent_play method for offline download
2025-06-24 21:54:30 +08:00
jenken827 ffc14ea14c feature:add crypt cmd (#342) 2025-06-24 19:05:46 +08:00
Jake Liu 25df3daba5 chore(google_photo): update titles in getFakeRoot (#343)
chore(google_photo): update titles in getFakeRoot to use constants instead of hardcoded strings
2025-06-24 18:18:53 +08:00
Dgs ce3cb2e31e feat(quark_open): add quark open driver support (#324) 2025-06-24 18:02:15 +08:00
ShenLin afe23986d2 chore(issue): Update issue templates with improved descriptions and links (#337)
Enhanced bug and feature request templates with bilingual descriptions, default titles, and updated documentation links. Added new contact options in config.yml, including a Telegram chat link. Improved clarity and localization for user instructions.
2025-06-24 11:24:40 +08:00
Suyunjing 0026f0c860 fix(ci):Fixed webversion (#333)
* Revert "fix(ci):fixed webversion (#332)"

This reverts commit 9e69b2aaa3.

* Fixed webversion

Signed-off-by: Suyunjing <69945917+Suyunmeng@users.noreply.github.com>

---------

Signed-off-by: Suyunjing <69945917+Suyunmeng@users.noreply.github.com>
2025-06-24 07:12:18 +08:00
Suyunjing 9e69b2aaa3 fix(ci):fixed webversion (#332)
fix(ci):fixed webversion bugs

Signed-off-by: Suyunjing <69945917+Suyunmeng@users.noreply.github.com>
2025-06-24 00:26:52 +08:00
MadDogOwner af71deb407 fix(cloudreve_v4): reference error in the refreshToken method (#328) 2025-06-24 00:01:19 +08:00
MadDogOwner fe079cf0a3 fix(cloudreve_v4): update rename api path to /file/rename (#331) 2025-06-23 23:59:01 +08:00
Suyunmeng cf85d49b6c fix(dropbox):Disable Dropbox's default use of the online API 2025-06-23 20:04:40 +08:00
Suyunjing 96cf2f7cf9 fix(fs):Repair file loss caused by special reasons when moving files (#321)
* fix(move):Fix file move logic

* fix(move):fixed move logic
2025-06-23 19:48:17 +08:00
MadDogOwner b0736d2d02 fix(cloudreve_v4): change upS3 callback method from POST to GET (#323) 2025-06-23 19:35:48 +08:00
Xi Xu 49213c1321 fix(setting): update PDF and EPUB viewer URLs (#297)
- Change PDF.js viewer URL from protocol-relative to HTTPS and updates parameter from "url" to "file" for proper document loading
- Also standardize EPUB.js viewer to use HTTPS protocol for consistency
2025-06-23 11:32:22 +08:00
Suyunmeng 64dd3cb047 fix(ci):fixed changelog ci (#302) 2025-06-22 20:48:10 +08:00
Timer 12fd52b6b7 docs(README_cn): format document links as list to sync with other languages. (#279)
Fix #272
2025-06-22 19:06:00 +08:00
Suyunmeng 27533d0e20 fixed(drive):Delete old Dropbox renewapi (#296)
* add dropbox api

* fixed(api):Delete old dropbox renew api

---------

Signed-off-by: Suyunmeng <69945917+Suyunmeng@users.noreply.github.com>
Co-authored-by: pikachuim <pikachuim@qq.com>
2025-06-22 18:52:55 +08:00
Ray 34a2eeb4a9 删除曲奇云盘驱动 (#294)
* Update all.go 删除quqi

Signed-off-by: Ray <eiauo.ray@gmail.com>

* Delete drivers/quqi directory删除quqi驱动

Signed-off-by: Ray <eiauo.ray@gmail.com>

---------

Signed-off-by: Ray <eiauo.ray@gmail.com>
2025-06-22 18:48:26 +08:00
Pikachu Ren 652e4ba1cb add dropbox api (#295) 2025-06-22 18:28:35 +08:00
hshpy 639b5cf7c2 fix(net):empty file download error (#282) 2025-06-22 14:21:45 +08:00
Jimmy Alexander b5c1386645 fix: typo and outdated - compose yaml (#263)
* Update docker-compose.yml

Image not exist

Signed-off-by:  Jimmy Alexander <142508054+integer2bit@users.noreply.github.com>

* chore: update docker-compose.yml image to docker hub

Signed-off-by:  Jimmy Alexander <142508054+integer2bit@users.noreply.github.com>

---------

Signed-off-by: Jimmy Alexander <142508054+integer2bit@users.noreply.github.com>
2025-06-22 12:22:21 +08:00
SenkjM 041868dfb8 docs: add channel and update compose config (#272)
* fix:remove-compose-version

Signed-off-by: SenkjM <112735335+SenkjM@users.noreply.github.com>

* mod : add Channel

* docs:update README

---------

Signed-off-by: SenkjM <112735335+SenkjM@users.noreply.github.com>
2025-06-22 00:41:25 +08:00
ILoveScratch cfbc157477 chore(ci): remove issue-related automation workflows (#257) 2025-06-21 15:14:24 +08:00
KirCute 5d44806064 fix(upload): revert #79 (#248) 2025-06-21 00:16:19 +08:00
Suyunmeng fc8b99c862 chore:fixed issue translate permissions
Signed-off-by: Suyunmeng <sumengjing@outlook.com>
2025-06-20 23:14:28 +08:00
Suyunmeng 24560b43c0 chore:fixed issue translate
Signed-off-by: Suyunmeng <sumengjing@outlook.com>
2025-06-20 23:08:50 +08:00
Suyunmeng 39ca385778 chore:Fixed docker release CI
Update release.yml

Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>

Update release.yml

Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>

chore(ci):Fixed CI bugs

Update release_linux_musl_arm.yml

Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>

Update release_linux_musl.yml

Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>

Update release_freebsd.yml

Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>

Update release_linux_musl_arm.yml

Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>

Update release_linux_musl.yml

Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>

Update release_freebsd.yml

Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>

Update release.yml

Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>

Update release_android.yml

Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>

Update release_docker.yml

Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>

Update release_docker.yml

Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>

chore:Fixed docker ci
2025-06-20 22:44:39 +08:00
ILoveScratch ef0531ad40 feat(ci): add changelog content to release content (#233) 2025-06-20 19:24:29 +08:00
ShenLin 12540a8abc fix: http2 content-length (#224) 2025-06-20 17:57:14 +08:00
ILoveScratch 0f5ed14fe2 feat(fs): add cross-storage move support (#211)
* feat(fs): add cross-storage move support

* fix(fs): add check before moving files

* fix(fs): changed error detect method

---------

Co-authored-by: ShenLin <773933146@qq.com>
2025-06-20 17:54:24 +08:00
Pikachu Ren ca55b89322 remove alist from repo (#230)
* remove alist from repo

* remove alist from repo

* remove alist from repo
2025-06-20 17:41:16 +08:00
Suyunmeng a3c7cb059d chore:Change Logo URL and fixed aliyundrive open bugs (#208)
* Fix Logo URL

* fixed aliyunpan_open

* fixed aliyundrive bugs

* fixed onlineapi bugs

* fixed onlineapi bugs

* Fixed Bugs

* Rollback

* fixed

* fixed onlineapi

* fixed driver

---------

Signed-off-by: Suyunmeng <sumengjing@outlook.com>
2025-06-19 21:20:29 +08:00
Pikachu Ren 0f8545133b add text output for error message (#210)
* mod rank for AccessToken

* del alist_v2

* add error message from remote

---------

Co-authored-by: Suyunmeng <sumengjing@outlook.com>
2025-06-19 20:25:45 +08:00
Suyunmeng 72fad1be2e Delete Lark Drive (#201) 2025-06-19 16:38:51 +08:00
Pikachu Ren b7ce7f172b Dev pika (#202)
* mod rank for AccessToken

* del alist_v2

---------

Co-authored-by: Suyunmeng <sumengjing@outlook.com>
2025-06-19 16:25:07 +08:00
Hantong Chen 248c041711 fix(setting): update preview url (#198) 2025-06-19 15:05:29 +08:00
j2rong4cn 70b937e031 Revert "feat(log): add error logging middleware for improved error handling (#182)"
This reverts commit 5e8d8d070a.
2025-06-19 09:56:45 +08:00
Hantong Chen 79521db8e0 fix(ci): add workflow_dispatch for beta_release and build 2025-06-18 23:27:23 +08:00
Hantong Chen 015d3ecd00 fix(ci): add auth header when access GitHub CI 2025-06-18 23:27:23 +08:00
Hantong Chen 89451b6d98 fix(ci): use OpenListTeam/cgo-actions@v1.1.2 2025-06-18 23:27:23 +08:00
Hantong Chen 681cb6c8a4 fix(ci): freebsd 14.1 is deprecated (#187) 2025-06-18 22:17:21 +08:00
Suyunmeng c2d1316f65 fix(115open) fixed rate_limit bugs (#161)
* fixed 115 bugs

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

* Fixed 115 open bugs

* fixed bugs

---------

Signed-off-by: Suyunmeng <sumengjing@outlook.com>
2025-06-18 21:32:23 +08:00
Kuingsmile 5e8d8d070a feat(log): add error logging middleware for improved error handling (#182) 2025-06-18 20:37:16 +08:00
Pikachu Ren c7c0bfe810 mod rank for AccessToken (#181) 2025-06-18 18:09:36 +08:00
Inori e9c73b52db fix(Dockerfile): add jq package (#168) 2025-06-18 14:26:42 +08:00
Kuingsmile 7d24a5d45f feat: add file visibility checks for windows (#39)
* feat: add file visibility checks for windows

* fix: fix build error

* refactor: optimize thie ishidden

---------

Co-authored-by: Hantong Chen <70561268+cxw620@users.noreply.github.com>
2025-06-17 23:25:02 +08:00
Hantong Chen 3ab309e00e refactor: adjust CI process (#125)
* feat(cmd/lang): allow setting frontend path when generate lang files

* chore(ci): remove ci for auto_lang (done by frontend ci)
2025-06-17 22:35:02 +08:00
Pikachu Ren 8822eef97e chore(api):Add online api refresh method (#143)
* Add Official API Refresh Interface(Baiduyun)

* add UseOnlineAPI & APIAddress
add _refreshToken using APIAddress

* fix return

* Modify the frontend display using the default API refresh method

* Fixed display and operation related issues

* fixed aliyundrive_open old refresh

---------

Co-authored-by: Suyunmeng <sumengjing@outlook.com>
2025-06-17 22:13:28 +08:00
KirCute 7613f886d0 fix(123open): add rate limit (#144) 2025-06-17 18:49:32 +08:00
xxxxxfpx fe02a989bd feat(123pan): support 123Open (#93) 2025-06-17 18:38:25 +08:00
Suyunmeng 2bed40cfce chore(Dockerfile): add jq package (#142)
Add jq package

Signed-off-by: Suyunmeng <sumengjing@outlook.com>
2025-06-17 18:38:22 +08:00
XZB-1248 87ca1b96ae fix(189pc): crashes when upload cancelled (#79)
* fix(189pc): crashes when upload cancelled

Signed-off-by: XZB-1248 <28593573+XZB-1248@users.noreply.github.com>

* fix(189pc): replace semaphore with errgroup.Group.SetLimit

---------

Signed-off-by: XZB-1248 <28593573+XZB-1248@users.noreply.github.com>
Co-authored-by: KirCute <951206789@qq.com>
2025-06-17 00:13:31 +08:00
KirCute 5a4649c929 feat(alias): support parallel write (#69)
* feat(alias): support parallel write

* fix(alias): lack `err` in `errors.Join()`
2025-06-17 00:13:01 +08:00
MadDogOwner 2e2cec05fd fix(cloudreve): remove unnecessary finish increment in upload functions (#62)
* fix(cloudreve): remove unnecessary finish increment in upload functions

* fix(cloudreve_v4): remove unnecessary finish increment in upload functions
2025-06-17 00:12:45 +08:00
Hantong Chen b1afadd129 chore: update project meta (#51)
* chore: update project meta (partial)

* chore: update README

* chore: update pdf preview

* revert: use old hash

* chore: update logo file url
2025-06-16 16:29:45 +08:00
410680876f1 a59ad9a84e fix(lanzou): fix removing JavaScript comments from response data (#37)
* 修复清理js中块注释的bug

移除块注释,目前只将开始“/*”和结束的“*/”移除,未将注释中内容移除

Signed-off-by: 410680876f1 <71364356+410680876f1@users.noreply.github.com>

* 修复清理js中注释的bug

移注释,目前只将注释标识符号清楚,注释中内容被遗留了下来
感谢大佬@Kuingsmile的代码审核

Signed-off-by: 410680876f1 <71364356+410680876f1@users.noreply.github.com>

* 代码格式化

Signed-off-by: 410680876f1 <71364356+410680876f1@users.noreply.github.com>

---------

Signed-off-by: 410680876f1 <71364356+410680876f1@users.noreply.github.com>
Co-authored-by: Hantong Chen <70561268+cxw620@users.noreply.github.com>
2025-06-16 16:28:08 +08:00
Suyunmeng 2e889fb07d chore(ci): fixed dockerhub ci process (#97)
* add DockerHub

* fixed dockerhub

* Update dockerhub CI

* Update DockerHub

* fixed bugs

* fixed CI Bugs

* Update auto_lang.yml

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

* fixed release

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

* Update test_docker.yml

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

* Delete hub

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

* Delete hub

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

* test build

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

* Simplify actions

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

* Simplify actions test

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

* Simplify actions test Successful ,Rollback Environments

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

* Update release_docker.yml

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

* Update test_docker.yml

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

* Update auto_lang.yml

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

* Update auto_lang.yml

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

* Update auto_lang.yml

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

* Update test_docker.yml

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

* Update release_docker.yml

Signed-off-by: Suyunmeng <sumengjing@outlook.com>

---------

Signed-off-by: Suyunmeng <sumengjing@outlook.com>
2025-06-16 14:16:45 +08:00
Suyunmeng d95c4f0127 chore: change the CDN link of the logo and modify the OCR port (#84)
* Change the CDN link of the logo and modify the OCR port

* Update

* Rollback OCR interface
2025-06-15 23:19:25 +08:00
Hantong Chen 1c58d11d62 chore: update build.sh & add loongarch64 support (#28)
* chore: update build.sh

* chore: update ci build

* chore: update ci build GitAuthor

* feat(build.sh): fix web release download & add loongarch64 build (#63)

chore(ci): fix web download & add loongarch64 & update cgo-actions to v1.1.1

* chore: temporary build test

* revert(build.sh): change to release used url

* feat(build.sh): add set -e for build script

* fix(build.sh): fix web release download logic

* fix(build.sh): remove TODO comment

* feat(build.sh): update GitAuthor to bot@openlist.team

* feat(build.sh): update GitAuthor

* fix: using fsSL in curl & add info of desktop client back

* chore: refine beta release workflow comments

---------

Co-authored-by: Yinan Qin <39023210+elysia-best@users.noreply.github.com>
2025-06-14 23:16:42 +08:00
Xinchen e11c390c4d fix(cli): Fixed links to documentation in the CLI (#71)
Co-authored-by: reschen <reschen@126.com>
2025-06-14 20:21:14 +08:00
KirCute 2965915bed chore(deps): switch the dependency from KirCute/sftpd-alist to OpenListTeam/sftpd-openlist (#64) 2025-06-14 16:04:13 +08:00
KirCute da1cfd1945 chore(deps): remove dependency KirCute/ftpserverlib-pasvportmap (#61) 2025-06-14 15:56:51 +08:00
YaoSiQian 8a29790327 chore(ci): using latest musl-compilers (#23)
* chore(ci): using `latest` musl-compilers

https://github.com/OpenListTeam/OpenList/pull/3#pullrequestreview-2921194381

Signed-off-by: YaoSiQian <admin@yaosiqian.cn>

* chore(ci): using `latest` musl-compilers in beta_release CI

---------

Signed-off-by: YaoSiQian <admin@yaosiqian.cn>
Co-authored-by: Hantong Chen <cxwdyx620@gmail.com>
2025-06-13 17:01:24 +08:00
Kuingsmile 7cd8f648c8 fix: change app name in cmd (#36) 2025-06-13 15:19:25 +08:00
Kuingsmile b8e6083e19 chore: remove deprecated vtencent drive (#33) 2025-06-13 12:55:52 +08:00
Yinan Qin 3f821bdcd1 revert: using old salt value (#29)
Signed-off-by: Yinan Qin <39023210+elysia-best@users.noreply.github.com>
2025-06-13 12:47:51 +08:00
Hantong Chen 9e05c81d9c chore: update project logo (#26) 2025-06-12 23:29:35 +08:00
zyk2507 f1552b67a0 chore(setting): update repo name in default announcement (#27)
chore(SETTING)/update repo name in default announcement
2025-06-12 23:28:33 +08:00
Hanson-zhy 20d1d5b479 chore(README): update README, add progress intro (#21)
* Update README_cn.md

* Update README_cn.md

* Update README.md

* Update README_ja.md

* Update README_ja.md

* Update README_ja.md

* Update README_ja.md

---------

Co-authored-by: Hantong Chen <70561268+cxw620@users.noreply.github.com>
2025-06-12 22:03:18 +08:00
Kuingsmile fdcc2f136e chore: change module name to OpenListTeam/OpenList (#2)
* Enable blank issue

* chore(README.md): update docs (temporally)

* Update FUNDING.yml

* chore: purge README.md

* chore: change module name to OpenListTeam/OpenList

* fix: fix link errors

* chore: remove v3 in module name

* fix: resolve some conficts

* fix: resolve conficts

* docs: update with latest file

---------

Co-authored-by: ShenLin <773933146@qq.com>
Co-authored-by: Hantong Chen <cxwdyx620@gmail.com>
Co-authored-by: joshua <i@joshua.su>
Co-authored-by: Hantong Chen <70561268+cxw620@users.noreply.github.com>
2025-06-12 22:02:46 +08:00
Yinan Qin 5feb86ceee chore(docs&ci): change links in files & fix github ci and docker ci (#3)
* Enable blank issue

* chore(README.md): update docs (temporally)

* Update FUNDING.yml

* chore: purge README.md

* Update README.md

Alist改为OpenList

* Update README_cn.md

Alist改为OpenList

* Update README.md

漏了一处

* Update README_ja.md

Alist改为OpenList

* Update README_cn.md

漏了一处

* Update CODE_OF_CONDUCT.md

更改链接

* Update README.md

更新tg链接

* Update README_cn.md

更新tg链接

* Update README_ja.md

更新tg链接

* chore(build&docs): use new links in build and github templates

* Update README.md

更新团队名

* chore: disable translation update, change beta release into artifacts

* fix: disable docker build and name the uploaded artifacts

* fix typo

* Update README_cn.md

更新团队名称

* Update README_ja.md

更新

* Update project name in CONTRIBUTING.md

* Update README_cn.md

更新

* Update README.md

更新

* Update README_ja.md

* fix: fix artifact name

* chore(build.sh): use original musl.cc

* fix(ci): fix action artifacts upload

* Update CODE_OF_CONDUCT.md

TG更改为Telegram

* Update README_cn.md

更新论坛链接

* Update README.md

更新论坛链接

* Update README_ja.md

更新论坛链接

* feat: update community based call back for onedrive

* chore(ci): update musl.cc link

* chore: use openlist as name instead of default OpenList

* Update user.go

* chore: fix artifact name

* feat(ci): add docker build test

* fix: add more platforms

* fix: explicitly use docker.io

* fix: fix typo

* fix(docker): fix test build push platform

* chore: change to OpenListTeam

* Update CODE_OF_CONDUCT.md

* doc: update org name

* docs: change repo urls

* feat: release docker image to ghcr.io on tagging

* fix: fix the name of test_docker

* build: update the names in docker-compose and docker file

* chore: rename

---------

Co-authored-by: ShenLin <773933146@qq.com>
Co-authored-by: Hantong Chen <cxwdyx620@gmail.com>
Co-authored-by: joshua <i@joshua.su>
Co-authored-by: 绎泽 <yize@tencent.to>
Co-authored-by: zyk2507 <93830642+zyk2507@users.noreply.github.com>
2025-06-12 21:29:43 +08:00
zyk2507 ee783fa1be chore(CONTRIBUTING): update to new OpenList-Frontend 2025-06-12 17:58:55 +08:00
ShenLin 0bcb4fe16d chore(README): update project name
Update FUNDING.yml

chore: purge README.md

Update project name in CONTRIBUTING.md

Update README.md

Alist改为OpenList

Update README_cn.md

Alist改为OpenList

Update README.md

漏了一处

Update README_ja.md

Alist改为OpenList

Update README_cn.md

漏了一处

Update CODE_OF_CONDUCT.md

更改链接

Update README.md

更新tg链接

Update README_cn.md

更新tg链接

Update README_ja.md

更新tg链接

Update README.md

更新团队名

Update README_cn.md

更新团队名称

Update README_ja.md

更新

Update README_cn.md

更新

Update README.md

更新

Update README_ja.md

Update CODE_OF_CONDUCT.md

TG更改为Telegram

Update README_cn.md

更新论坛链接

Update README.md

更新论坛链接

Update README_ja.md

更新论坛链接
2025-06-12 16:56:22 +08:00
Hantong Chen 4f57bd3ae6 chore(README.md): update docs (temporally) 2025-06-12 16:56:22 +08:00
Hantong Chen cf42fe6a40 chore: allow blank issue 2025-06-12 16:56:18 +08:00
Hantong Chen c4775521c6 chore(README.md): reminder of fork
fix: remove `alistgo.com`
2025-06-11 16:14:44 +08:00
MadDogOwner ffa03bfda1 feat(cloudreve_v4): add Cloudreve V4 driver (#8470 closes #8328 #8467)
* feat(cloudreve_v4): add Cloudreve V4 driver implementation

* fix(cloudreve_v4): update request handling to prevent token refresh loop

* feat(onedrive): implement retry logic for upload failures

* feat(cloudreve): implement retry logic for upload failures

* feat(cloudreve_v4): support cloud sorting

* fix(cloudreve_v4): improve token handling in Init method

* feat(cloudreve_v4): support share

* feat(cloudreve): support reference

* feat(cloudreve_v4): support version upload

* fix(cloudreve_v4): add SetBody in upLocal

* fix(cloudreve_v4): update URL structure in Link and FileUrlResp
2025-05-24 13:38:43 +08:00
Andy Hsu 630cf30af5 feat(115_open): implement rate limiting for API requests 2025-05-11 13:39:32 +08:00
Andy Hsu bc5117fa4f fix(115_open): add delay in MakeDir function to handle rate limiting 2025-05-02 16:53:39 +08:00
yoclo 11e7284824 fix: prevent guest user from updating profile (#8447) 2025-04-29 23:14:16 +08:00
MadDogOwner b2b91a9281 feat(doubao): add get_download_info API and download_api option (#8428) 2025-04-27 20:00:25 +08:00
MadDogOwner f541489d7d fix(netease_music): change ListResp size fields from string to int64 (#8417) 2025-04-27 19:59:30 +08:00
bigQY 6d9c554f6f feat: add UseLargeThumbnail for 139 (#8424) 2025-04-27 19:58:45 +08:00
Mmx e532ab31ef fix: remove auth middleware for authn login (#8407) 2025-04-27 19:58:09 +08:00
Mmx bf0705ec17 fix: shebang of entrypoint.sh (#8408) 2025-04-27 19:56:34 +08:00
gdm257 17b42b9fa4 fix(mega): use newest file for same filename (#8422 close #8344)
Mega supports duplicate names but alist does not support.
In `List()` method, driver will return multiple files with same name.
That makes alist to use oldest version file for listing/downloading.
So it is necessary to filter old same name files in a folder.
After fixes, all CRUD work normally.

Refs #8344
2025-04-27 19:56:04 +08:00
Sam- Pan(潘绍森) 41bdab49aa fix(139): incorrect host (#8368)
* fix: correct new personal cloud path for 139Driver

* Update drivers/139/driver.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix bug

---------

Co-authored-by: panshaosen <19802021493@139.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: j2rong4cn <253551464@qq.com>
2025-04-19 14:29:12 +08:00
Lin Tianchuan 8f89c55aca perf(local): avoid duplicate parsing of VideoThumbPos (#7812)
* feat(local): support percent for video thumbnail

The percentage determines the point in the video (as a percentage of the total duration) at which the thumbnail will be generated.

* feat(local): support both time and percent for video thumbnail

* refactor(local): avoid duplicate parsing of VideoThumbPos
2025-04-19 14:27:13 +08:00
wxnq b449312da8 fix(docker_release): avoid duplicate occupation in docker image (#8393 close #8388)
* fix(ci): modify the method of adding permissions

* fix(build): modify the method of adding permissions(to keep up with ci)
2025-04-19 14:26:19 +08:00
MadDogOwner 52d4e8ec47 fix(lanzou): remove JavaScript comments from response data (#8386)
* feat(lanzou): add RemoveJSComment function to clean JavaScript comments from HTML

* feat(lanzou): remove comments from share page data in getFilesByShareUrl function

* fix(lanzou): optimize RemoveJSComment function to improve comment removal logic
2025-04-19 14:24:43 +08:00
New Future 28e5b5759e feat(azure_blob): implement GetRootId interface in Addition struct (#8389)
fix failed get dir
2025-04-19 14:23:48 +08:00
asdfghjkl 477c43971f feat(doubao_share): support doubao_share link (#8376)
Co-authored-by: anobodys <anobodys@gmail.com>
2025-04-19 14:22:43 +08:00
Yifan Gao 0a9921fa79 fix(aliyundrive_open): resolve file duplication issues and improve path handling (#8358)
* fix(aliyundrive_open): resolve file duplication issues and improve path handling

1. Fix file duplication by implementing a new removeDuplicateFiles method that cleans up duplicate files after operations
2. Change Move operation to use "ignore" for check_name_mode instead of "refuse" to allow moves when destination has same filename
3. Set Copy operation to handle duplicates by removing them after successful copy
4. Improve path handling for all file operations (Move, Rename, Put, MakeDir) by properly maintaining the full path of objects
5. Implement GetRoot interface for proper root object initialization with correct path
6. Add proper path management in List operation to ensure objects have correct paths
7. Fix path handling in error cases and improve logging of failures

* refactor(aliyundrive_open): change error logging to warnings for duplicate file removal

Updated the Move, Rename, and Copy methods to log warnings instead of errors when duplicate file removal fails, as the primary operations have already completed successfully. This improves the clarity of logs without affecting the functionality.

* Update drivers/aliyundrive_open/util.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-04-19 14:22:12 +08:00
Lee CQ 88abb323cb feat(url-tree): implement the Put interface to support adding links directly to the UrlTree on the web side (#8312)
* feat(url-tree)支持PUT

* feat(url-tree) UrlTree更新时,需要将路径和内容分割 #8303

* fix: stdpath.Join call

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Andy Hsu <i@nn.ci>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-04-12 17:27:56 +08:00
asdfghjkl f0b1aeaf8d feat(doubao): support upload (#8302 close #8335)
* feat(doubao): support upload

* fix(doubao): fix file list cursor

* fix: handle strconv.Atoi err

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: anobodys <anobodys@gmail.com>
Co-authored-by: Andy Hsu <i@nn.ci>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-04-12 17:12:40 +08:00
Yifan Gao c8470b9a2a fix(fs): remove old target object from cache before updating (#8352) 2025-04-12 17:09:46 +08:00
Dgs d0ee90cd11 fix(thunder): fix login issue (#8342 close #8288) 2025-04-12 17:05:58 +08:00
Dgs 544a7ea022 fix(pikpak&pikpak_share): fix WebPackageName (#8305) 2025-04-12 17:03:58 +08:00
j2rong4cn 4f5cabc725 feat: add h2c for http server (#8294)
* feat: add h2c for http server

* chore(config): add EnableH2c option
2025-04-12 17:02:51 +08:00
j2rong4cn a2f266277c fix(net): unexpected write (#8291 close #8281) 2025-04-12 17:01:52 +08:00
jerry a4bfbf8a83 fix(ipfs): fix problems (#8252)
* fix: 🐛 (ipfs): fix the list error caused by not proper join path function

使用更加规范的路径拼接,修复了有中文或符号的路径无法正常访问的问题

* refactor: 命名规范

* 删除多余的条件判断

* fix: 使用withresult方法重构代码,添加get方法,提高性能

* fix: 允许get方法获取目录

去除多余的判断

* fix: 允许copy,rename,move进行覆写

* fix: 修复move方法导致的目录被删除

* refactor: 整理关于返回Path的代码

* fix: 修复由于get方法导致的ipfs路径无法访问

* fix: 修复path处理错误的get方法

修复get方法,删除意外加入的目录

* fix: fix path join

use path join instead of filepath join to avoid os problem

* fix: rm filepath ref

---------

Co-authored-by: Andy Hsu <i@nn.ci>
2025-04-12 17:01:30 +08:00
j2rong4cn ddffacf07b perf: optimize IO read/write usage (#8243)
* perf: optimize IO read/write usage

* .

* Update drivers/139/driver.go

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

---------

Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2025-04-12 16:55:31 +08:00
xiaoQQya 3375c26c41 perf(quark_uc&quark_uc_tv): native proxy multithreading (#8287)
* perf(quark_uc): native proxy multithreading

* perf(quark_uc_tv): native proxy multithreading

* chore(fs): file query result add id
2025-04-03 20:50:29 +08:00
asdfghjkl ab68faef44 fix(baidu_netdisk): add another video crack api (#8275)
Co-authored-by: anobodys <anobodys@gmail.com>
2025-04-03 20:44:49 +08:00
New Future 2e21df0661 feat(driver): add Azure Blob Storage driver (#8261)
* add azure-blob driver

* fix nested folders copy

* feat(driver): add Azure Blob Storage driver

实现 Azure Blob Storage 驱动,支持以下功能:
- 使用共享密钥身份验证初始化连接
- 列出目录和文件
- 生成临时 SAS URL 进行文件访问
- 创建目录
- 移动和重命名文件/文件夹
- 复制文件/文件夹
- 删除文件/文件夹
- 上传文件并支持进度跟踪

此驱动允许用户通过 AList 平台无缝访问和管理 Azure Blob Storage 中的数据。

* feat(driver): update help doc for Azure Blob

* doc(readme): add new driver

* Update drivers/azure_blob/driver.go

fix(azure): fix name check

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update README.md

doc(readme): fix the link

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix(azure): fix log and link

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-04-03 20:43:21 +08:00
MadDogOwner af18cb138b feat(139): add option ReportRealSize (#8244 close #8141)
* feat(139): handle family upload errors

* feat(139): add option `ReportRealSize`

* Update drivers/139/driver.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-04-03 20:41:59 +08:00
j2rong4cn 31c55a2adf fix(archive): unable to preview (#8248)
* fix(archive): unable to preview

* fix bug
2025-04-03 20:41:05 +08:00
MadDogOwner 465dd1703d feat(cloudreve): s3 policy support (#8245)
* feat(cloudreve): s3 policy support

* fix(cloudreve): correct potential off-by-one error in `etags` initialization
2025-04-03 20:40:19 +08:00
j2rong4cn a6304285b6 fix: revert "refactor(net): pass request header" (#8269)
https://github.com/AlistGo/alist/pull/8031/commits/5be50e77d9ad8d67e343aa7e9380bcdd2506ae8f
2025-04-03 20:35:52 +08:00
YangXu affd0cecd1 fix(pikpak&pikpak_share): update algorithms (#8278) 2025-04-03 20:35:14 +08:00
MadDogOwner 37640221c0 fix(doubao): update file size type to int64 (#8289) 2025-04-03 20:34:27 +08:00
Andy Hsu e4bd223d1c fix(deps): update 115-sdk-go to v0.1.5 2025-04-03 20:29:53 +08:00
jerry 0cde4e73d6 feat(ipfs): better ipfs support (#8225)
* feat: ✨ better ipfs support

fixed mfs crud, added ipns support

* Update driver.go

clean up
2025-03-27 23:25:23 +08:00
Ljcbaby 7b62dcb88c fix(baidu_netdisk): deplicate retry (#8210 redo #7972, link #8180) 2025-03-27 23:22:55 +08:00
never lee c38dc6df7c fix(115_open): support multipart upload (#8229)
Co-authored-by: neverlee <neverlea@formail.com>
2025-03-27 23:22:08 +08:00
MadDogOwner 5668e4a4ea feat(doubao): add Doubao driver (#8232 closes #8020 #8206)
* feat(doubao): implement List()

* feat(doubao): implement Link()

* feat(doubao): implement MakeDir()

* refactor(doubao): add type Object to store key

* feat(doubao): implement Move()

* feat(doubao): implement Rename()

* feat(doubao): implement Remove()
2025-03-27 23:21:42 +08:00
KirCute 1335f80362 feat(archive): support multipart archives (#8184 close #8015)
* feat(archive): multipart support & sevenzip tool

* feat(archive): rardecode tool

* feat(archive): support decompress multi-selected

* fix(archive): decompress response filter internal

* feat(archive): support multipart zip

* fix: more applicable AcceptedMultipartExtensions interface
2025-03-27 23:20:44 +08:00
KirCute 704d3854df feat(alist_v3): support forward archive requests (#8230)
* feat(alist_v3): support forward archive requests

* fix: encode all inner path
2025-03-27 23:18:34 +08:00
MadDogOwner 44cc71d354 fix(cloudreve): enable SetContentLength for uploading to local policy (#8228 close #8174)
* fix(cloudreve): upload failure to return error msg instead of deletion success

* fix(cloudreve): enable SetContentLength for uploading to local policy

* refactor(cloudreve): move local policy upload logic to utils for better error handling

* refactor(cloudreve): unified upload code style

* refactor(cloudreve): improve user agent handling
2025-03-27 23:18:15 +08:00
KirCute 9a9aee9ac6 feat(alias): support writing to non-ambiguous paths (#8216)
* feat(alias): support writing to non-ambiguous paths

* feat(alias): support extract concurrency

* fix(alias): extract url no pass query
2025-03-27 23:17:45 +08:00
KirCute 4fcc3a187e fix(traffic): duplicate semaphore release when uploading (#8211 close #8180) 2025-03-27 23:15:47 +08:00
Ljcbaby 10a76c701d fix(db): support postgres trust/peer mode (#8198 close #8066) 2025-03-27 23:15:04 +08:00
KirCute 6e13923225 fix(sftp-server): postgre cannot store control characters (#8188 close #8186) 2025-03-27 23:14:36 +08:00
Andy Hsu 32890da29f fix(115_open): upgrade 115-sdk-go dependency to v0.1.4 2025-03-21 19:06:09 +08:00
Andy Hsu 758554a40f fix(115_open): upgrade 115-sdk-go dependency to v0.1.3 (close #8169) 2025-03-19 21:47:42 +08:00
Andy Hsu 4563aea47e fix(115_open): rename delay to take effect (close #8156) 2025-03-18 22:25:04 +08:00
Andy Hsu 35d6f3b8fc fix(115_open): upgrade sdk (close #8151) 2025-03-18 22:21:50 +08:00
j2rong4cn b4e6ab12d9 refactor: FilterReadMeScripts (#8154 close #8150)
* refactor: FilterReadMeScripts

* .
2025-03-18 22:02:33 +08:00
Andy Hsu 3499c4db87 feat: 115 open driver (#8139)
* wip: 115 open

* chore(go.mod): update 115-sdk-go dependency version

* feat(115_open): implement directory management and file operations

* chore(go.mod): update 115-sdk-go dependency to v0.1.1 and adjust callback handling in driver

* chore: rename driver
2025-03-17 00:52:09 +08:00
hshpy d20f41d687 fix: missing handling of RangeReadCloser (#8146) 2025-03-16 22:14:44 +08:00
Andy Hsu d16ba65f42 fix(lang): initialize configuration in LangCmd before generating language JSON file 2025-03-16 16:37:33 +08:00
hshpy c82e632ee1 fix: potential XSS vulnerabilities (#7923)
* fix: potential XSS vulnerabilities

* feat: support filter and render for readme.md

* chore: set ReadMeAutoRender to true

* fix attachFileName undefined

---------

Co-authored-by: Andy Hsu <i@nn.ci>
2025-03-15 23:28:40 +08:00
折纸飞机 04f5525f20 fix(s3): incorrectly added slash before the Bucket name (#8083 close #8001) 2025-03-15 00:21:24 +08:00
shniubobo 28b61a93fd feat(webdav): support oc:checksums (#8064 close #7472)
Ref: #7472
2025-03-15 00:21:07 +08:00
j2rong4cn 0126af4de0 fix(crypt): premature close of MFile (#8132 close #8119)
* fix(crypt): premature close of MFile

* refactor
2025-03-15 00:13:30 +08:00
MadDogOwner 7579d44517 fix(onedrive): set req.ContentLength (#8081)
* fix(onedrive): set req.ContentLength

* fix(onedrive_app): set req.ContentLength

* fix(cloudreve): set req.ContentLength
2025-03-15 00:12:37 +08:00
MadDogOwner 5dfea714d8 fix(cloudreve): use milliseconds timestamp in last_modified (#8133) 2025-03-15 00:12:15 +08:00
Ljcbaby 370a6c15a9 fix(baidu_netdisk): remove duplicate retry (#7972) 2025-03-01 19:00:36 +08:00
Ljcbaby 2570707a06 feat(baidu_netdisk): support dynamical slice size for low bandwith upload case (#7965)
* 动态分片尺寸

* 补充严格测试结果
2025-03-01 18:46:05 +08:00
j2rong4cn 4145734c18 refactor(net): pass request header (#8031 close #8008)
* refactor(net): pass request header

* feat(proxy): add `Etag` to response header

* refactor
2025-03-01 18:35:34 +08:00
KirCute 646c7bcd21 fix(archive): use another sign for extraction (#7982) 2025-03-01 18:34:33 +08:00
KirCute cdc41595bc feat(github): support GPG verification (#7996 close #7986)
* feat(github): support GPG verification

* chore
2025-02-24 23:12:23 +08:00
KirCute_ECT 79bef0be9e chore: fix build failed (#8005) 2025-02-16 15:11:48 +08:00
KirCute_ECT c230f24ebe fix(archive): decode filename when decompressing zips (#7998 close #7988) 2025-02-16 12:25:01 +08:00
KirCute_ECT 30d8c20756 feat(archive): support deprioritize previewing (#7984) 2025-02-16 12:24:10 +08:00
KirCute_ECT 3b71500f23 feat(traffic): support limit task worker count & file stream rate (#7948)
* feat: set task workers num & client stream rate limit

* feat: server stream rate limit

* upgrade xhofe/tache

* .
2025-02-16 12:22:11 +08:00
foxxorcat 399336b33c fix(189pc): transfer rename (#7958)
* fix(189pc): transfer rename

* fix: OverwriteUpload

* fix: change search method

* fix

* fix
2025-02-16 12:21:34 +08:00
KirCute_ECT 36b4204623 feat(github): support github proxy (#7979 close #7963) 2025-02-16 12:21:03 +08:00
YangRucheng f25be154c6 fix(ilanzou): add header X-Forwarded-For to solve IP ban (#7977)
* fix: warning

* feat: ip header

* fix: ip header for fs link
2025-02-16 12:20:28 +08:00
Sakana ec3fc945a3 fix(feiji): modify the request header (#7902 close #7890) 2025-02-09 18:35:39 +08:00
MadDogOwner 3f9bed3d5f feat(bootstrap): add .url to proxy types (#7928) 2025-02-09 18:33:38 +08:00
Jealous b9ad18bd0a feat(recursive-move): Advanced conflict policy for preventing unintentional overwriting (#7906) 2025-02-09 18:32:57 +08:00
Jealous 0219c4e15a fix(index): fix the issue where ignored paths are not updated (#7907) 2025-02-09 18:31:43 +08:00
Feng.YJ d983a4ebcb refactor(cmd): use std runtime package to get go version info (#7964)
* refactor(cmd): use std `runtime` package to get go version info

- Remove the `GoVersion` variable.
- Remove overriding `GoVersion` by ldflags in `build.sh`.
- Get go version, OS and arch from the constants in the std `runtime` package instead of compile time.

* chore(ci): remove `GoVersion` flag from workflows

Remove GoVersion flag from beta_release.yml and build.yml workflows.

> Reduce compile-time dependencies.
2025-02-09 18:30:56 +08:00
Sakana f795807753 feat(github_releases): support dir size for show all version (#7938)
* refactor

* 修改默认 RepoStructure

* feat: 支持使用 gh-proxy
2025-02-09 18:30:38 +08:00
hshpy 6164e4577b fix: missing args when using alias driver (#7941 close #7932) 2025-02-05 19:22:10 +08:00
Sakana 39bde328ee fix(lenovonas_share): the size of the directory (#7914) 2025-02-01 17:32:58 +08:00
KirCute_ECT 779c293f04 fix(driver): implement canceling and updating progress for putting for some drivers (#7847)
* fix(driver): additionally implement canceling and updating progress for putting for some drivers

* refactor: add driver archive api into template

* fix(123): use built-in MD5 to avoid caching full

* .

* fix build failed
2025-02-01 17:29:55 +08:00
abc1763613206 b9f397d29f fix(139): restore the Account handling, partially reverts #7850 (#7900 close #7784) 2025-01-30 11:25:41 +08:00
Jiang Xiang d53eecc229 fix(febbox): panic due to slice out of range (#7898 close #7889) 2025-01-30 11:24:07 +08:00
Andy Hsu f88fd83d4a feat(ci): use go-cross/cgo-actions for dev build 2025-01-28 18:57:09 +08:00
Andy Hsu 226c34929a feat(ci): add build info for beta release 2025-01-27 21:32:59 +08:00
j2rong4cn 027edcbe53 refactor(patch): execute all patches in dev version (#7807) 2025-01-27 20:49:24 +08:00
Snowykami fd51f34efa feat(misskey): add misskey driver (#7864) 2025-01-27 20:47:52 +08:00
Sakana bdd9774aa7 feat(github_releases): add support for github_releases driver (#7844 close #7842)
* feat(github_releases): 添加对 GitHub Releases 的支持

* feat(github_releases): 增加目录大小和更新时间,增加请求缓存

* Feat(github_releases): 可选填入 GitHub token 来提高速率限制或访问私有仓库

* Fix(github_releases): 修复仓库无权限或不存在时的异常

* feat(github_releases): 支持显示所有版本,开启后不显示文件夹大小

* feat(github_releases): 兼容无子目录
2025-01-27 20:28:44 +08:00
Jealous 258b8f520f feat(recursive-move): add overwrite option to preventing unintentional overwriting (#7868 closes #7382,#7719)
* feat(recursive-move): add `overwrite` option to preventing unintentional overwriting

* chore: rearrange code order
2025-01-27 20:25:39 +08:00
Jiang Xiang 99f39410f2 fix(s3): escape CopySource request header when copying files (#7860 close #7858) 2025-01-27 20:23:13 +08:00
Shelton Zhu 267120a8c8 fix(115): fix offline download (#7845 close #7794)
* feat(115): use multi url for list files & change download url api

* fix(115): fix offline download. (close #7794)
2025-01-27 20:20:55 +08:00
KirCute_ECT 5eff8cc7bf feat(upload): support rapid upload on web (#7851) 2025-01-27 20:20:09 +08:00
KirCute_ECT d5ec998699 feat(task): allow retry canceled (#7852) 2025-01-27 20:18:10 +08:00
LaoShui 23f3178f39 chore(README): formatting spacing in README links (#7879) [skip ci] 2025-01-27 20:13:35 +08:00
MadDogOwner cafdb4d407 fix(139): correct path handling in groupGetFiles (#7850 closes #7848,#7603)
* fix(139): correct path handling in groupGetFiles

* perf(139): reduce the number of requests in groupGetFiles

* refactor(139): check authorization expiration (#10)

* refactor(139): check authorization expiration

* fix bug

* chore(139): update api version to 7.14.0

---------

Co-authored-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
2025-01-27 20:11:21 +08:00
Jealous 0d4c63e9ff feat(fs): display the existing filename in error message (#7877) 2025-01-27 20:09:17 +08:00
j2rong4cn 5c5d8378e5 fix(archive): unable to preview (#7843)
* fix(archive): unrecognition zip

* feat(archive): add tree for zip meta

* fix bug

* refactor(archive):  meta cache time use Link Expiration first

* feat(archive): return sort policy in meta (#2)

* refactor

* perf(archive): reduce new network requests

---------

Co-authored-by: KirCute_ECT <951206789@qq.com>
2025-01-27 20:08:56 +08:00
j2rong4cn 2be0c3d1a0 feat(alias): add DownloadConcurrency and DownloadPartSize option (#7829)
* fix(net): goroutine logic bug (AlistGo/alist#7215)

* Fix goroutine logic bug

* Fix bug

---------

Co-authored-by: hpy hs <hshpy.pengyu@gmail.com>

* perf(net): sequential and dynamic concurrency

* fix(net): incorrect error return

* feat(alias):  add `DownloadConcurrency` and `DownloadPartSize` option

* feat(net): add `ConcurrencyLimit`

* pref(net): create `chunk` on demand

* refactor

* refactor

* fix(net): `r.Closers.Add` has no effect

* refactor

---------

Co-authored-by: hpy hs <hshpy.pengyu@gmail.com>
2025-01-27 20:08:39 +08:00
foxxorcat bdcf450203 fix: resolve concurrent read/write issues in WrapObjName (#7865) 2025-01-27 20:06:18 +08:00
Jealous c2633dd443 fix(workflow): use the dev version of the web for beta releases (#7862)
* fix(workflow): use dev version of the web for beta releases

* chore(config): check version string by prefix
2025-01-23 22:49:35 +08:00
KirCute_ECT 11b6a6012f fix(copy): use Link and Put when the driver does not support copying (#7834) 2025-01-18 23:52:02 +08:00
Jealous 59e02287b2 feat(fs): add overwrite option to preventing unintentional overwriting (#7809) 2025-01-18 23:39:07 +08:00
KirCute_ECT bb40e2e2cd feat(archive): archive manage (#7817)
* feat(archive): archive management

* fix(ftp-server): remove duplicate ReadAtSeeker realization

* fix(archive): bad seeking of SeekableStream

* fix(archive): split internal and driver extraction api

* feat(archive): patch

* fix(shutdown): clear decompress upload tasks

* chore

* feat(archive): support .iso format

* chore
2025-01-18 23:28:12 +08:00
j2rong4cn ab22cf8233 feat: add Reference interface to driver (#7805)
* feat: add `Reference` interface to driver

* feat(123_share): support reference 123pan
2025-01-18 23:26:58 +08:00
MadDogOwner 880cc7abca fix(139): use personal_new by default (#7836) 2025-01-18 23:24:09 +08:00
Jealous b60da9732f feat(offline-download): allow using offline download tools in any storage (#7716)
* Feat(offline-download): allow using thunder offline download tool in any storage

* Feat(offline-download): allow using 115 offline download tool in any storage

* Feat(offline-download): allow using pikpak offline download tool in any storage

* style(offline-download): unify offline download tool names

* feat(offline-download): show available offline download tools only

* Fix(offline-download): update unmodified tool names.

---------

Co-authored-by: Andy Hsu <i@nn.ci>
2025-01-10 21:24:44 +08:00
KirCute_ECT e04114d102 feat(github): add github api driver (#7717)
* feat(github): add github api driver

* fix: filter submodule operation

* feat: rename, copy and move, but with bugs

* fix: move and copy returns 422

* fix: change TargetPath in rename msg from parent path to new self path

* fix: add non-commit mutex

* pref(github): use net/http to put blob

* chore: add a help message to `ref` addition
2025-01-10 20:59:58 +08:00
KirCute_ECT 51bcf83511 feat(url-tree): support url tree driver writing (#7779 close #5166)
* feat: support url tree writing

* fix: meta writable

* feat: disable writable via addition
2025-01-10 20:50:56 +08:00
KirCute_ECT 25b4b55ee1 feat(ftp-server): support resumable downloading (#7792) 2025-01-10 20:50:20 +08:00
Jiang Xiang 6812ec9a6d fix(ilanzou): add accept-encoding request header (#7796 close #7759) 2025-01-10 20:49:50 +08:00
Lin Tianchuan 31a7470865 feat(local): support both time and percent for video thumbnail (#7802)
* feat(local): support percent for video thumbnail

The percentage determines the point in the video (as a percentage of the total duration) at which the thumbnail will be generated.

* feat(local): support both time and percent for video thumbnail
2025-01-10 20:48:45 +08:00
Mmx 687124c81d ci(build_docker): merge build_docker into release_docker workflow (#7755)
* feat(ci): merge build_docker workflow into release_docker

* fix(ci): logics of docker meta
2025-01-01 21:29:59 +08:00
foxxorcat e4439e66b9 fix:(baidu_photo): upload erron -6 (#7760 close #7744)
* fix:(baidu_photo): upload erron -6

* fix(baidu_photo):api add bdstoken
2025-01-01 21:13:34 +08:00
MadDogOwner 7fd4ac7851 fix(139): update familyGetFiles pagination logic (#7748 close #7711) 2024-12-30 22:55:47 +08:00
KirCute_ECT 6745dcc139 feat(task): attach creator to user of the context (#7729) 2024-12-30 22:55:09 +08:00
KirCute_ECT aa1082a56c feat(sftp-server): do not generate host key until first enabled (#7734) 2024-12-30 22:54:37 +08:00
Jealous ed149be84b feat(index): add disable index option for storages (#7730) 2024-12-30 22:52:55 +08:00
Sakana 040dc14ee6 fix(lenovonas_share): stoken expire (#7727) 2024-12-30 22:51:39 +08:00
Mmx 4dce53d72b feat(docker release): improve aria2 image, add aio image (#7750)
* build: add argument INSTALL_ARIA2 to dockerfile

* feat: run aria2 in main entrypoint

* feat(ci): environment matrix for docker release

* improve(ci): allow overwrite artifacts in docker release

* fix(ci): permission of alist binary in docker; entrypoint logic

* improve(aria2): move aria2 data to /opt/aria2; fix permission issues

References:

https://github.com/AlistGo/with_aria2/pull/13

Co-authored-by: GoodbyeNJN <cc@fuckwall.cc>

* fix(ci): aio image is not taking effect

* fix(build): tar command in aria2 installation process

(cherry picked from commit 647285408354807bae64df6a20fefb696ff787de)

---------

Co-authored-by: GoodbyeNJN <cc@fuckwall.cc>
2024-12-30 22:51:05 +08:00
j2rong4cn 365fc40dfe fix: static page to limit request method (#7745 close #7667) 2024-12-30 22:49:18 +08:00
KirCute_ECT 5994c17b4e feat(patch): upgrade patch module (#7738)
* feat(patch): upgrade patch module

* chore(patch): add docs

* fix(patch): skip and rewrite invalid last launched version

* fix(patch): turn two functions into patches
2024-12-30 22:48:33 +08:00
Jealous 42243b1517 feat(thunder): add offline download tool (#7673)
* feat(thunder): add offline download tool

* fix(thunder): improve error handling and parse file size in status response

---------

Co-authored-by: Andy Hsu <i@nn.ci>
2024-12-25 21:23:58 +08:00
KirCute_ECT 48916cdedf fix(permission): enhance the strictness of permissions (#7705 close #7680)
* fix(permission): enhance the strictness of permissions

* fix: add initial permissions to admin
2024-12-25 21:17:58 +08:00
Feng.YJ 5ecf5e823c fix(webauthn): handle error when removing webauthn credential (#7689) 2024-12-25 21:16:34 +08:00
KirCute_ECT c218b5701e fix(115): support float QPS (#7677) 2024-12-25 21:16:03 +08:00
KirCute_ECT 77d0c78bfd feat(sftp-server): public key login (#7668) 2024-12-25 21:15:06 +08:00
j2rong4cn db5c601cfe fix(crypt): add sign to thumbnail (#6611) 2024-12-25 21:13:54 +08:00
KirCute_ECT 221cdf3611 feat(s3): support custom host presign (#7699 close #7696) 2024-12-25 21:13:23 +08:00
KirCute_ECT 40b0e66efe feat(ftp-server): treat moving across file systems as copying (#7704 close #7701)
* feat(ftp-server): treat moving across file systems as copying

* fix: ensure compatibility across different fs on the same driver
2024-12-25 21:12:30 +08:00
KirCute_ECT b72e85a73a fix(ftp-server): rewrite download in a more appropriate method (#7656) 2024-12-25 21:11:45 +08:00
KirCute_ECT 6aaf5975c6 fix(ftp-server): work unproperly when base url is not root (#7693)
* fix(ftp-server): work unproperly when base url is not root

* fix: avoid merge conflict
2024-12-25 21:11:36 +08:00
MadDogOwner bb2aec20e4 fix(139): handle upload file conflicts (#7692) 2024-12-25 21:11:05 +08:00
KirCute_ECT d7aa1608ac feat(task): add speed monitor (#7655) 2024-12-25 21:09:54 +08:00
j2rong4cn db99224126 perf: Speed ​​of database initialization (#7694)
* perf: 优化非sqlite3数据库时初始化慢的问题

* refactor
2024-12-25 21:08:22 +08:00
MadDogOwner b8bd14f99b fix(lanzou): missing parameter (#7678 close #7210) 2024-12-17 22:05:52 +08:00
hshpy 331885ed64 fix(net): close of closed channel (#7580) 2024-12-17 22:04:27 +08:00
Andy Hsu cf58ab3a78 chore(config): disable FTP and SFTP by default 2024-12-12 21:04:14 +08:00
KirCute_ECT 33ba7f1521 feat: sftp server support (#7643)
* feat: sftp server support

* fix(sftp-server): try fix build failed

* fix: sftp download lack
2024-12-12 20:51:43 +08:00
KirCute_ECT 201e25c17f fix(ftp-server): large transfer leads to client timeout (#7639)
* fix(ftp-server): client timeout to wait a large file upload to netdisk

* fix(ftp-server): driver alist v3 upload failed and temp files do not be deleted
2024-12-12 20:50:00 +08:00
Andy Hsu ecefa5e0eb ci: fix desktop beta release trigger 2024-12-10 20:21:51 +08:00
KirCute_ECT 650b03aeb1 feat: ftp server support (#7634 close #1898)
* feat: ftp server support

* fix(ftp): incorrect mode for dirs in LIST returns
2024-12-10 20:17:46 +08:00
KirCute_ECT 7341846499 perf(task): merge requests of operating selected (#7637) 2024-12-10 19:30:50 +08:00
MadDogOwner a3908fd9a6 fix(139): update APIs (#7591 close #7603)
* fix(139): update family cloud API

* fix(139): update API of familyGetLink

* feat(139): support group (close #7603)

* docs: add `139 group` to Readme

* feat(139): support multipart upload (close: #7444)

* feat(139): add custom upload part size option

* fix: missing right big quote

---------

Co-authored-by: Andy Hsu <i@nn.ci>
2024-12-09 23:54:21 +08:00
MadDogOwner 2a035302b2 fix(cloudreve): support upload to remote and OneDrive storage (#7632 close #6882)
- Add support for remote and OneDrive storage types
- Implement new upload methods for different storage types
- Update driver to handle various storage policies
- Add error handling and session cleanup for failed uploads
2024-12-09 23:35:44 +08:00
MadDogOwner 016e169c41 feat(139): support multipart upload (close: #7444) (#7630)
* feat(139): support multipart upload (close: #7444)

* feat(139): add custom upload part size option
2024-12-09 23:34:29 +08:00
Joseph Chris 088120df82 feat(sso): add custom extra scope support (#7577) 2024-12-09 23:33:46 +08:00
Shelton Zhu aa45a82914 fix(115): fix login bug (#7626 close #7614 close #7620) 2024-12-09 23:33:07 +08:00
shingyu 5084d98398 fix(onedrive): fix timeout error (#7551 close #7506) 2024-12-08 17:06:33 +08:00
YangXu fa15c576f0 fix(pikpak): remove oauth2 method (#7567 close #7545) 2024-12-07 17:03:46 +08:00
foxxorcat 2d3605c684 fix(baidu_photo): cookie login fix download error (#7602) 2024-12-07 17:02:52 +08:00
alist666 492b49d77a Update README.md 2024-12-07 01:00:25 +08:00
Kuingsmile 94915b2148 fix(baidu_netdisk): update fileToObj to use ServerCtime and ServerMtime (#7535) 2024-11-21 22:41:23 +08:00
YangXu 2dec756f23 fix(pikpak&pikpak_share): captcha_sign error (#7530 close #7481 close #7482) 2024-11-21 22:40:39 +08:00
j2rong4cn 4c0cffd29b fix(net): close of closed channel (#7529) 2024-11-21 22:39:14 +08:00
Rirmach 25c5e075a9 fix(local): Preserve file owner when copying (#7528) 2024-11-21 22:38:41 +08:00
Mmx 398c04386a feat(sso): generate and verify OAuth state with go-cache (#7527) 2024-11-21 22:38:04 +08:00
Mmx 12b429584e feat(security): generating random string with crypto rand (#7525) 2024-11-21 22:37:19 +08:00
Mmx 150dcc2147 fix(sso): OIDC compatibility mode (#7524) 2024-11-21 22:36:41 +08:00
Andy Hsu 0ba754fd40 fix(release): missing installation of zig 2024-11-17 23:11:03 +08:00
Andy Hsu 28d2367a87 fix(ci): no space left on device 2024-11-17 22:24:06 +08:00
BlueSkyXN a4ad98ee3e fix(pikpak): domain block and change to NET (#7350) 2024-11-17 20:03:04 +08:00
Jason-Fly 1c01dc6839 fix(storage): delete storage fails if a panic occurred during initialization (#7501)
* fix(storage): store storages map when init storage panic

* fix(drivers): add nil check to drop method
2024-11-16 13:20:49 +08:00
Jason-Fly c3c5843dce fix(terabox): panic due to slice out of range (#7499 close #7487) 2024-11-16 13:19:59 +08:00
Jason-Fly 6c38c5972d fix(terabox): big file upload issue (#7498 close #7490) 2024-11-16 13:18:49 +08:00
foxxorcat 0a46979c51 feat(115): enhance cache (#7479) 2024-11-08 22:08:50 +08:00
foxxorcat 67c93eed2b feat(baidu_netdisk,baidu_photo): add and fix hashinfo (#7469) 2024-11-08 22:08:25 +08:00
安稳 f58de9923a refactor(aliyunopen,config): Modify default properties (#7476) 2024-11-08 22:07:35 +08:00
foxxorcat 2671c876f1 revert: "fix(115): enforce 20GB file size limit on uploadev"
This reverts commit 216e3909f3.
2024-11-02 21:08:19 +08:00
Andy Hsu e707fa38f1 ci: remove specific tag for freebsd action 2024-11-02 17:05:00 +08:00
859 changed files with 85928 additions and 14347 deletions
+2 -2
View File
@@ -3,11 +3,11 @@
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: xhofe # Replace with a single Ko-fi username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: ['https://alist.nn.ci/guide/sponsor.html']
custom: []
@@ -0,0 +1,98 @@
name: "错误报告"
description: 错误报告 / 问题
title: "[BUG] 请修改标题为您遇到的问题"
labels: [bug]
body:
- type: markdown
attributes:
value: |
感谢您花时间填写此错误报告。
请**务必**确认您的问题无重复,且不是因为您的操作、网络或第三方软件问题。
- type: checkboxes
attributes:
label: 请确认以下事项
description: |
您必须阅读、检查、确认、同意以下内容,否则您的问题一定会被直接关闭。
或者您可以去[讨论区](https://github.com/OpenListTeam/OpenList/discussions)。
options:
- label: |
我已确认阅读并同意 [AGPL-3.0 第15条](https://www.gnu.org/licenses/agpl-3.0.txt#:~:text=15.%20Disclaimer%20of%20Warranty.) 。
本程序不提供任何明示或暗示的担保,使用风险由您自行承担。
- label: |
我已确认阅读并同意 [AGPL-3.0 第16条](https://www.gnu.org/licenses/agpl-3.0.txt#:~:text=16.%20Limitation%20of%20Liability.) 。
无论何种情况,版权持有人或其他分发者均不对使用本程序所造成的任何损失承担责任。
- label: |
我确认我的描述清晰,语法礼貌,能帮助开发者快速定位问题,并符合社区规则。
- label: |
我已确认阅读了[OpenList文档](https://doc.oplist.org)。
- label: |
我已确认没有重复的问题或讨论。
- label: |
我已确认是`OpenList`的问题,而不是其他原因(例如 [网络](https://doc.oplist.org/faq/howto#tls-handshake-timeout-read-connection-reset-by-peer-dns-lookup-failed-connect-connection-refused-client-timeout-exceeded-while-awaiting-headers-no-such-host-1) ,`依赖`或`操作`)。
- label: |
我认为此问题必须由`OpenList`处理,而非第三方。
- label: |
我已确认这个问题在最新版本中没有被修复。
- label: |
我没有阅读这个清单,只是闭眼选中了所有的复选框,请关闭这个 Issue 。
- type: input
id: version
attributes:
label: OpenList 版本(必填)
description: |
您使用的是哪个版本的软件?请不要使用`latest`或`master`作为答案。
placeholder: v4.xx.xx
validations:
required: true
- type: input
id: driver
attributes:
label: 使用的存储驱动(必填)
description: |
您使用的是哪个存储驱动?
placeholder: "例如: OneDrive"
validations:
required: true
- type: textarea
id: bug-description
attributes:
label: 问题描述(必填)
validations:
required: true
- type: textarea
id: logs
attributes:
label: 日志(必填)
description: |
请复制粘贴错误日志,或者截图。(可隐藏隐私字段) [查看方法](https://doc.oplist.org/faq/howto#%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%9A%E4%BD%8Dbug)
validations:
required: true
- type: textarea
id: config
attributes:
label: 配置文件内容(必填)
description: |
请提供您的`OpenList`应用的配置文件,并截图相关存储配置。(可隐藏隐私字段)
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: 复现链接(可选)
description: |
请提供能复现此问题的链接。
- type: checkboxes
id: aigenerated
attributes:
label: AI生成内容
description: 必须且只能勾选一项,请勿删除或修改声明文字。
options:
- label: 我使用了AI工具生成此内容
- label: 我没有使用AI工具生成此内容
- type: input
id: ai-model
attributes:
label: AI模型是
description: 如果使用了AI工具,请填写模型名称;未使用则留空。
placeholder: xxx
@@ -0,0 +1,98 @@
name: "Bug Report"
description: Bug Report / Issue
title: "[BUG] Please modify the title to describe the issue you are facing"
labels: [bug]
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to fill out this bug report.
Please **make sure** your issue is not a duplicate and is not caused by your own operation, network, or third-party software.
- type: checkboxes
attributes:
label: Please confirm the following
description: |
You must read, check, confirm, and agree to all the following, otherwise your issue will definitely be closed directly.
Or you can go to the [discussions](https://github.com/OpenListTeam/OpenList/discussions).
options:
- label: |
I have read and agree to [AGPL-3.0 Section 15](https://www.gnu.org/licenses/agpl-3.0.txt#:~:text=15.%20Disclaimer%20of%20Warranty.) .
The program is provided "as is" without any warranties; you bear all risks of using it.
- label: |
I have read and agree to [AGPL-3.0 Section 16](https://www.gnu.org/licenses/agpl-3.0.txt#:~:text=16.%20Limitation%20of%20Liability.) .
The copyright holders and distributors are not liable for any damages resulting from the use or inability to use the program.
- label: |
I confirm my description is clear, polite, helps developers quickly locate the issue, and complies with community rules.
- label: |
I have read the [OpenList documentation](https://doc.oplist.org).
- label: |
I confirm there are no duplicate issues or discussions.
- label: |
I confirm this is an `OpenList` issue, not caused by other reasons (such as [network](https://doc.oplist.org/faq/howto#tls-handshake-timeout-read-connection-reset-by-peer-dns-lookup-failed-connect-connection-refused-client-timeout-exceeded-while-awaiting-headers-no-such-host-1), dependencies, or operation).
- label: |
I believe this issue must be handled by `OpenList` and not by a third party.
- label: |
I confirm this issue is not fixed in the latest version.
- label: |
I have not read these checkboxes and therefore I just ticked them all, Please close this issue.
- type: input
id: version
attributes:
label: OpenList Version (required)
description: |
What version of the software are you using? Please do not use `latest` or `master` as the answer.
placeholder: v4.xx.xx
validations:
required: true
- type: input
id: driver
attributes:
label: Storage Driver Used (required)
description: |
Which storage driver are you using?
placeholder: "e.g. OneDrive"
validations:
required: true
- type: textarea
id: bug-description
attributes:
label: Bug Description (required)
validations:
required: true
- type: textarea
id: logs
attributes:
label: Logs (required)
description: |
Please copy and paste any relevant log output or screenshots. (You may mask sensitive fields) [Guide](https://doc.oplist.org/faq/howto#how-to-quickly-locate-bugs)
validations:
required: true
- type: textarea
id: config
attributes:
label: Configuration File Content (required)
description: |
Please provide your `OpenList` application's configuration file and a screenshot of the relevant storage configuration. (You may mask sensitive fields)
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Reproduction Link (optional)
description: |
Please provide a link to a repo or page that can reproduce this issue.
- type: checkboxes
id: aigenerated
attributes:
label: AI Generated Content
description: Select exactly one option. Do not delete or modify the disclosure text.
options:
- label: I used AI tools to generate this content
- label: I did not use AI tools to generate this content
- type: input
id: ai-model
attributes:
label: AI model used
description: If you used AI tools, enter the model name; otherwise leave this blank.
placeholder: xxx
@@ -0,0 +1,64 @@
name: "功能请求"
description: 功能请求 / 增强
title: "[Feature] 请修改标题为您的功能名称"
labels: [enhancement]
body:
- type: checkboxes
attributes:
label: 请确认以下事项
description: |
您必须阅读、检查、确认、同意以下内容,否则您的问题可能会被直接关闭。
或者您可以去[讨论区](https://github.com/OpenListTeam/OpenList/discussions)。
options:
- label: |
我已确认阅读并同意 [AGPL-3.0 第15条](https://www.gnu.org/licenses/agpl-3.0.txt#:~:text=15.%20Disclaimer%20of%20Warranty.) 。
本程序不提供任何明示或暗示的担保,使用风险由您自行承担。
- label: |
我已确认阅读并同意 [AGPL-3.0 第16条](https://www.gnu.org/licenses/agpl-3.0.txt#:~:text=16.%20Limitation%20of%20Liability.) 。
无论何种情况,版权持有人或其他分发者均不对使用本程序所造成的任何损失承担责任。
- label: |
我确认我的描述清晰,语法礼貌,能帮助开发者快速定位问题,并符合社区规则。
- label: |
我已确认阅读了[OpenList文档](https://doc.oplist.org)。
- label: |
我已确认没有重复的问题或讨论。
- label: |
我认为此问题必须由`OpenList`处理,而非第三方。
- label: |
我已确认此功能尚未被实现。
- label: |
我已确认此功能是合理的,且有普遍需求,并非我个人需要。
- label: |
我没有阅读这个清单,只是闭眼选中了所有的复选框,请关闭这个 Issue 。
- type: textarea
id: feature-description
attributes:
label: 需求描述
validations:
required: true
- type: textarea
id: suggested-solution
attributes:
label: 实现思路
description: |
实现此需求的解决思路。
- type: textarea
id: additional-context
attributes:
label: 附加信息
description: |
相关的任何其他上下文或截图,或者你觉得有帮助的信息
- type: checkboxes
id: aigenerated
attributes:
label: AI生成内容
description: 必须且只能勾选一项,请勿删除或修改声明文字。
options:
- label: 我使用了AI工具生成此内容
- label: 我没有使用AI工具生成此内容
- type: input
id: ai-model
attributes:
label: AI模型是
description: 如果使用了AI工具,请填写模型名称;未使用则留空。
placeholder: xxx
@@ -0,0 +1,64 @@
name: "Feature Request"
description: Feature Request / Enhancement
title: "[Feature] Please modify the title to your feature name"
labels: [enhancement]
body:
- type: checkboxes
attributes:
label: Please confirm the following
description: |
You must read, check, confirm, and agree to all the following, otherwise your request may be closed directly.
Or you can go to the [discussions](https://github.com/OpenListTeam/OpenList/discussions).
options:
- label: |
I have read and agree to [AGPL-3.0 Section 15](https://www.gnu.org/licenses/agpl-3.0.txt#:~:text=15.%20Disclaimer%20of%20Warranty.).
The program is provided "as is" without any warranties; you bear all risks of using it.
- label: |
I have read and agree to [AGPL-3.0 Section 16](https://www.gnu.org/licenses/agpl-3.0.txt#:~:text=16.%20Limitation%20of%20Liability.).
The copyright holders and distributors are not liable for any damages resulting from the use or inability to use the program.
- label: |
I confirm my description is clear, polite, helps developers quickly locate the issue, and complies with community rules.
- label: |
I have read the [OpenList documentation](https://doc.oplist.org).
- label: |
I confirm there are no duplicate issues or discussions.
- label: |
I believe this issue must be handled by `OpenList` and not by a third party.
- label: |
I confirm this feature has not been implemented yet.
- label: |
I confirm this feature is reasonable and has general demand, not just my personal need.
- label: |
I have not read these checkboxes and therefore I just ticked them all, Please close this issue.
- type: textarea
id: feature-description
attributes:
label: Feature Description
validations:
required: true
- type: textarea
id: suggested-solution
attributes:
label: Suggested Solution
description: |
Solution or approach to achieve this feature.
- type: textarea
id: additional-context
attributes:
label: Additional Information
description: |
Any other context or screenshots related to this feature request, or information you find helpful.
- type: checkboxes
id: aigenerated
attributes:
label: AI Generated Content
description: Select exactly one option. Do not delete or modify the disclosure text.
options:
- label: I used AI tools to generate this content
- label: I did not use AI tools to generate this content
- type: input
id: ai-model
attributes:
label: AI model used
description: If you used AI tools, enter the model name; otherwise leave this blank.
placeholder: xxx
-81
View File
@@ -1,81 +0,0 @@
name: "Bug report"
description: Bug report
labels: [bug]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report, please **confirm that your issue is not a duplicate issue and not because of your operation or version issues**
感谢您花时间填写此错误报告,请**务必确认您的issue不是重复的且不是因为您的操作或版本问题**
- type: checkboxes
attributes:
label: Please make sure of the following things
description: |
You must check all the following, otherwise your issue may be closed directly. Or you can go to the [discussions](https://github.com/alist-org/alist/discussions)
您必须勾选以下所有内容,否则您的issue可能会被直接关闭。或者您可以去[讨论区](https://github.com/alist-org/alist/discussions)
options:
- label: |
I have read the [documentation](https://alist.nn.ci).
我已经阅读了[文档](https://alist.nn.ci)。
- label: |
I'm sure there are no duplicate issues or discussions.
我确定没有重复的issue或讨论。
- label: |
I'm sure it's due to `AList` and not something else(such as [Network](https://alist.nn.ci/faq/howto.html#tls-handshake-timeout-read-connection-reset-by-peer-dns-lookup-failed-connect-connection-refused-client-timeout-exceeded-while-awaiting-headers-no-such-host) ,`Dependencies` or `Operational`).
我确定是`AList`的问题,而不是其他原因(例如[网络](https://alist.nn.ci/zh/faq/howto.html#tls-handshake-timeout-read-connection-reset-by-peer-dns-lookup-failed-connect-connection-refused-client-timeout-exceeded-while-awaiting-headers-no-such-host),`依赖`或`操作`)。
- label: |
I'm sure this issue is not fixed in the latest version.
我确定这个问题在最新版本中没有被修复。
- type: input
id: version
attributes:
label: AList Version / AList 版本
description: |
What version of our software are you running? Do not use `latest` or `master` as an answer.
您使用的是哪个版本的软件?请不要使用`latest`或`master`作为答案。
placeholder: v3.xx.xx
validations:
required: true
- type: input
id: driver
attributes:
label: Driver used / 使用的存储驱动
description: |
What storage driver are you using?
您使用的是哪个存储驱动?
placeholder: "for example: Onedrive"
validations:
required: true
- type: textarea
id: bug-description
attributes:
label: Describe the bug / 问题描述
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Reproduction / 复现链接
description: |
Please provide a link to a repo that can reproduce the problem you ran into. Please be aware that your issue may be closed directly if you don't provide it.
请提供能复现此问题的链接,请知悉如果不提供它你的issue可能会被直接关闭。
validations:
required: true
- type: textarea
id: config
attributes:
label: Config / 配置
description: |
Please provide the configuration file of your `AList` application and take a screenshot of the relevant storage configuration. (hide privacy field)
请提供您的`AList`应用的配置文件,并截图相关存储配置。(隐藏隐私字段)
validations:
required: true
- type: textarea
id: logs
attributes:
label: Logs / 日志
description: |
Please copy and paste any relevant log output.
请复制粘贴错误日志,或者截图
+12 -3
View File
@@ -1,5 +1,14 @@
blank_issues_enabled: false
blank_issues_enabled: true
contact_links:
- name: 问题和讨论
url: https://github.com/OpenListTeam/OpenList/discussions
about: 讨论、问题、想法等
- name: Questions & Discussions
url: https://github.com/alist-org/alist/discussions
about: Use GitHub discussions for message-board style questions and discussions.
url: https://github.com/OpenListTeam/OpenList/discussions
about: Discuss issues, ideas, etc.
- name: 即时聊天
url: https://t.me/OpenListTeam
about: 与我们聊天
- name: Chat
url: https://t.me/OpenListTeam
about: Chat with us
@@ -1,33 +0,0 @@
name: "Feature request"
description: Feature request
labels: [enhancement]
body:
- type: checkboxes
attributes:
label: Please make sure of the following things
description: You may select more than one, even select all.
options:
- label: I have read the [documentation](https://alist.nn.ci).
- label: I'm sure there are no duplicate issues or discussions.
- label: I'm sure this feature is not implemented.
- label: I'm sure it's a reasonable and popular requirement.
- type: textarea
id: feature-description
attributes:
label: Description of the feature / 需求描述
validations:
required: true
- type: textarea
id: suggested-solution
attributes:
label: Suggested solution / 实现思路
description: |
Solutions to achieve this requirement.
实现此需求的解决思路。
- type: textarea
id: additional-context
attributes:
label: Additional context / 附件
description: |
Any other context or screenshots about the feature request here, or information you find helpful.
相关的任何其他上下文或截图,或者你觉得有帮助的信息
+114
View File
@@ -0,0 +1,114 @@
<!--
PR title / PR 标题:
- Use Conventional Commits: `type(scope): summary`
- Allowed types: `feat`, `docs`, `fix`, `style`, `refactor`, `chore`
- Scope is required by the current PR title check.
- For breaking changes, add `!`: `feat(driver)!: change auth flow`
-->
## Summary / 摘要
<!--
Briefly describe what changed and why.
简要说明改了什么,以及为什么需要改。
-->
<!--
- List user-visible behavior changes.
- List important implementation changes.
- Mention config, storage, API, or compatibility changes if any.
- 列出用户可感知的行为变化。
- 列出重要实现变化。
- 如涉及配置、存储、API 或兼容性变化,请明确说明。
-->
- [ ] This PR has breaking changes.
/ 此 PR 包含破坏性变更。
- [ ] This PR changes public API, config, storage format, or migration behavior.
/ 此 PR 修改了公开 API、配置、存储格式或迁移行为。
- [ ] This PR requires corresponding changes in related repositories.
/ 此 PR 需要关联仓库同步修改。
Related repository PRs / 关联仓库 PR:
- OpenList-Frontend:
- OpenList-Docs:
## Related Issues / 关联 Issue
<!--
Use `Closes #123`, `Fixes #123`, or `Relates to #123`.
Remove this section if not applicable.
使用 `Closes #123`、`Fixes #123` 或 `Relates to #123`。
不适用时请删除本节。
-->
## Testing / 测试
<!--
Describe commands, platforms, and manual checks.
If not tested, explain why.
说明执行过的命令、测试平台和手动验证。
如果未测试,请说明原因。
-->
- [ ] `go test ./...`
- [ ] Manual test / 手动测试:
## Checklist / 检查清单
- [ ] I have read [CONTRIBUTING](https://github.com/OpenListTeam/OpenList/blob/main/CONTRIBUTING.md).
/ 我已阅读 [CONTRIBUTING](https://github.com/OpenListTeam/OpenList/blob/main/CONTRIBUTING.md)。
- [ ] 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.
/ 我已按适用情况使用 `gofmt`、`go fmt` 或 `prettier` 格式化变更代码。
- [ ] I have requested review from relevant maintainers or code owners where applicable.
/ 我已在适用情况下请求相关维护者或代码所有者审查。
## AI Disclosure / AI 使用声明
<!--
Please disclose any substantial AI assistance used in this PR.
Minor AI assistance, such as typo fixes, autocomplete, formatting suggestions,
or wording polish, does not need to be disclosed.
Remove this section if not applicable.
请披露此 PR 中使用的重要 AI 辅助内容。
轻微 AI 辅助,例如拼写修正、自动补全、格式建议或文字润色,无需披露。
如不适用,请删除本节。
Deliberate non-disclosure may be treated as a trust and compliance issue.
故意隐瞒 AI 使用情况可能被视为信任与合规问题。
-->
- [ ] This PR includes AI-assisted content.
/ 此 PR 包含 AI 辅助内容。
Tools used / 使用工具:
- [ ] ChatGPT
- [ ] Codex
- [ ] GitHub Copilot
- [ ] Claude
- [ ] Gemini
- [ ] Other (please specify) / 其他(请注明):
Usage scope / 使用范围:
- [ ] Code generation / 代码生成
- [ ] Refactoring / 重构
- [ ] Documentation / 文档
- [ ] Tests / 测试
- [ ] Translation / 翻译
- [ ] Review assistance / 审查辅助
- [ ] I have reviewed and validated all AI-assisted content included in this PR.
/ 我已审核并验证此 PR 中的所有 AI 辅助内容。
- [ ] I have ensured that all AI-assisted commits include `Co-Authored-By` attribution.
/ 我已确保所有 AI 辅助提交都包含 `Co-Authored-By` 归属信息。
- [ ] I can reproduce all AI-assisted content included in this PR without any AI tools.
/ 我可以在没有任何 AI 工具的情况下重现此 PR 中包含的所有 AI 辅助内容。
-21
View File
@@ -1,21 +0,0 @@
# Configuration for welcome - https://github.com/behaviorbot/welcome
# Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome
# Comment to be posted to on first time issues
newIssueWelcomeComment: >
Thanks for opening your first issue here! Be sure to follow the issue template!
# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome
# Comment to be posted to on PRs from first time contributors in your repository
newPRWelcomeComment: >
Thanks for opening this pull request! Please check out our contributing guidelines.
# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge
# Comment to be posted to on pull requests merged by a first time user
firstPRMergeComment: >
Congrats on merging your first pull request! We here at behavior bot are proud of you!
# It is recommend to include as many gifs and emojis as possible
-21
View File
@@ -1,21 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 44
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 20
# Issues with these labels will never be considered stale
exemptLabels:
- accepted
- security
- working
- pr-welcome
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: >
This issue was closed due to inactive more than 52 days. You can reopen or
recreate it if you think it should continue. Thank you for your contributions again.
-71
View File
@@ -1,71 +0,0 @@
name: auto_lang
on:
push:
branches:
- 'main'
paths:
- 'drivers/**'
- 'internal/bootstrap/data/setting.go'
- 'internal/conf/const.go'
- 'cmd/lang.go'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
auto_lang:
strategy:
matrix:
platform: [ ubuntu-latest ]
go-version: [ '1.21' ]
name: auto generate lang.json
runs-on: ${{ matrix.platform }}
steps:
- name: Setup go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- name: Checkout alist
uses: actions/checkout@v4
with:
path: alist
- name: Checkout alist-web
uses: actions/checkout@v4
with:
repository: 'alist-org/alist-web'
ref: main
persist-credentials: false
fetch-depth: 0
path: alist-web
- name: Generate lang
run: |
cd alist
go run ./main.go lang
cd ..
- name: Copy lang file
run: |
cp -f ./alist/lang/*.json ./alist-web/src/lang/en/ 2>/dev/null || :
- name: Commit git
run: |
cd alist-web
git add .
git config --local user.email "bot@nn.ci"
git config --local user.name "IlaBot"
git commit -m "chore: auto update i18n file" -a 2>/dev/null || :
cd ..
- name: Push lang files
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.MY_TOKEN }}
branch: main
directory: alist-web
repository: alist-org/alist-web
+120 -51
View File
@@ -1,8 +1,9 @@
name: beta release
name: Beta Release builds
on:
push:
branches: [ 'main' ]
branches: ["main"]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@@ -13,21 +14,17 @@ permissions:
jobs:
changelog:
strategy:
matrix:
platform: [ ubuntu-latest ]
go-version: [ '1.21' ]
name: Beta Release Changelog
runs-on: ${{ matrix.platform }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
- name: Create or update ref
id: create-or-update-ref
uses: ovsds/create-or-update-ref-action@v1
uses: ovsds/create-or-update-ref-action@1157b2991820188d5a8e6f22656775d1d171f762 # v1
with:
ref: tags/beta
sha: ${{ github.sha }}
@@ -41,15 +38,25 @@ jobs:
run: |
git tag -l
npx changelogithub --output CHANGELOG.md
# npx changelogen@latest --output CHANGELOG.md
- name: Upload assets
uses: softprops/action-gh-release@v2
- name: Upload assets to beta release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if ! gh release view beta; then
gh release create beta --prerelease --notes-file CHANGELOG.md
else
gh release edit beta --prerelease --notes-file CHANGELOG.md
fi
gh release upload beta "CHANGELOG.md" --clobber
- name: Upload assets to github artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
body_path: CHANGELOG.md
files: CHANGELOG.md
prerelease: true
tag_name: beta
name: beta changelog
path: ${{ github.workspace }}/CHANGELOG.md
compression-level: 0
if-no-files-found: error # 'warn' or 'ignore' are also available, defaults to `warn`
release:
needs:
@@ -57,68 +64,130 @@ jobs:
strategy:
matrix:
include:
- target: '!(*musl*|*windows-arm64*|*android*|*freebsd*)' # xgo
- target: "!(*musl*|*windows-arm64*|*windows7-*|*android*|*freebsd*)" # xgo and loongarch (exclude mips64le)
hash: "md5"
- target: 'linux-!(arm*)-musl*' #musl-not-arm
flags: ""
goflags: ""
- target: "linux-(mips|mips64|mipsle|mips64le|loong64)-musl*" # musl-compat-family
hash: "md5-linux-musl-mips"
flags: "-ldflags=-linkmode external -extldflags '-static -fpic'"
goflags: ""
musl_static: "true"
- target: "linux-!(arm*|mips|mips64|mipsle|mips64le|loong64)-musl*" # musl-not-arm (exclude compat-family)
hash: "md5-linux-musl"
- target: 'linux-arm*-musl*' #musl-arm
flags: "-ldflags=-linkmode external -extldflags '-static -fpic'"
goflags: ""
musl_static: "true"
- target: "linux-arm*-musl*" #musl-arm
hash: "md5-linux-musl-arm"
- target: 'windows-arm64' #win-arm64
flags: "-ldflags=-linkmode external -extldflags '-static -fpic'"
goflags: ""
musl_static: "true"
- target: "windows-arm64" #win-arm64
hash: "md5-windows-arm64"
- target: 'android-*' #android
flags: ""
goflags: ""
musl_static: "false"
- target: "windows7-*" #win7
hash: "md5-windows7"
flags: ""
goflags: "-tags=sqlite_cgo_compat"
musl_static: "false"
- target: "android-*" #android
hash: "md5-android"
- target: 'freebsd-*' #freebsd
flags: ""
goflags: ""
musl_static: "false"
- target: "freebsd-*" #freebsd
hash: "md5-freebsd"
flags: ""
goflags: ""
musl_static: "false"
name: Beta Release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: '1.22'
go-version: "1.27.1"
- name: Setup web
run: bash build.sh dev web
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FRONTEND_REPO: ${{ vars.FRONTEND_REPO }}
- name: Build
id: test-action
uses: go-cross/cgo-actions@v1
uses: OpenListTeam/cgo-actions@d760a8ec1a6be1f8ec181229e11cb2671797f9e0 # v1.3.0
with:
targets: ${{ matrix.target }}
flags: ${{ matrix.flags || '-ldflags=' }}
static-link-for-musl: true
musl-target-format: $os-$musl-$arch
github-token: ${{ secrets.GITHUB_TOKEN }}
out-dir: build
output: openlist-$target$ext
musl-base-url: "https://github.com/OpenListTeam/musl-compilers/releases/latest/download/"
x-flags: |
github.com/OpenListTeam/OpenList/v4/internal/conf.BuiltAt=$built_at
github.com/OpenListTeam/OpenList/v4/internal/conf.GitAuthor=The OpenList Projects Contributors <noreply@oplist.org>
github.com/OpenListTeam/OpenList/v4/internal/conf.GitCommit=$git_commit
github.com/OpenListTeam/OpenList/v4/internal/conf.Version=$tag
github.com/OpenListTeam/OpenList/v4/internal/conf.WebVersion=rolling
env:
GOFLAGS: ${{ matrix.goflags }}
- name: Verify musl binaries are static
if: matrix.musl_static == 'true'
run: |
set -e
shopt -s nullglob
files=(build/openlist-*-musl-*)
if [ ${#files[@]} -eq 0 ]; then
echo "No musl binaries found"
exit 1
fi
for f in "${files[@]}"; do
if readelf -l "$f" | grep -q "Requesting program interpreter"; then
echo "Dynamic binary detected: $f"
readelf -l "$f" | grep "Requesting program interpreter" || true
exit 1
fi
done
- name: Compress
run: |
bash build.sh zip ${{ matrix.hash }}
- name: Upload assets
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload assets to beta release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
for file in build/compress/*; do
gh release upload beta "$file" --clobber
done
- name: Clean illegal characters from matrix.target
id: clean_target_name
run: |
ILLEGAL_CHARS_REGEX='[":<>|*?\\/\r\n]'
CLEANED_TARGET=$(echo "${{ matrix.target }}" | sed -E "s/$ILLEGAL_CHARS_REGEX//g")
echo "Original target: ${{ matrix.target }}"
echo "Cleaned target: $CLEANED_TARGET"
echo "cleaned_target=$CLEANED_TARGET" >> $GITHUB_ENV
- name: Upload assets to github artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
files: build/compress/*
prerelease: true
tag_name: beta
desktop:
needs:
- release
name: Beta Release Desktop
runs-on: ubuntu-latest
steps:
- uses: peter-evans/create-or-update-comment@v4
with:
issue-number: 69
body: |
/release-beta
- triggered by @${{ github.actor }}
- commit sha: ${{ github.sha }}
- view files: https://github.com/alist-org/alist/tree/${{ github.sha }}
reactions: 'rocket'
token: ${{ secrets.MY_TOKEN }}
repository: alist-org/desktop-release
name: beta builds for ${{ env.cleaned_target }}
path: ${{ github.workspace }}/build/compress/*
compression-level: 0
if-no-files-found: error # 'warn' or 'ignore' are also available, defaults to `warn`
+52 -25
View File
@@ -1,10 +1,9 @@
name: build
name: Test Build
on:
push:
branches: [ 'main' ]
pull_request:
branches: [ 'main' ]
branches: ["main"]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@@ -14,35 +13,63 @@ jobs:
build:
strategy:
matrix:
platform: [ubuntu-latest]
go-version: [ '1.21' ]
name: Build
runs-on: ${{ matrix.platform }}
target:
- darwin-amd64
- darwin-arm64
- windows-amd64
- linux-arm64-musl
- linux-amd64-musl
- windows-arm64
- android-arm64
name: Build ${{ matrix.target }}
runs-on: ubuntu-latest
steps:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: benjlevesque/short-sha@v3.0
- uses: benjlevesque/short-sha@dbe07338b37c456ce06d23409b35a56a7815eef4 # v4.0
id: short-sha
- name: Install dependencies
run: |
sudo snap install zig --classic --beta
docker pull crazymax/xgo:latest
go install github.com/crazy-max/xgo@latest
sudo apt install upx
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: "1.27.1"
- name: Setup web
run: bash build.sh dev web
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FRONTEND_REPO: ${{ vars.FRONTEND_REPO }}
- name: Build
uses: OpenListTeam/cgo-actions@d760a8ec1a6be1f8ec181229e11cb2671797f9e0 # v1.3.0
with:
targets: ${{ matrix.target }}
flags: ${{ contains(matrix.target, '-musl') && '-ldflags=-linkmode external -extldflags ''-static -fpic''' || '-ldflags=' }}
static-link-for-musl: true
musl-target-format: $os-$musl-$arch
github-token: ${{ secrets.GITHUB_TOKEN }}
out-dir: build
x-flags: |
github.com/OpenListTeam/OpenList/v4/internal/conf.BuiltAt=$built_at
github.com/OpenListTeam/OpenList/v4/internal/conf.GitAuthor=The OpenList Projects Contributors <noreply@oplist.org>
github.com/OpenListTeam/OpenList/v4/internal/conf.GitCommit=$git_commit
github.com/OpenListTeam/OpenList/v4/internal/conf.Version=$tag
github.com/OpenListTeam/OpenList/v4/internal/conf.WebVersion=rolling
output: openlist$ext
- name: Verify musl binary is static
if: contains(matrix.target, '-musl')
run: |
bash build.sh dev
set -e
if readelf -l build/openlist | grep -q "Requesting program interpreter"; then
echo "Dynamic binary detected: build/openlist"
readelf -l build/openlist | grep "Requesting program interpreter" || true
exit 1
fi
- name: Upload artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: alist_${{ env.SHA }}
path: dist
name: openlist_${{ steps.short-sha.outputs.sha }}_${{ matrix.target }}
path: build/*
-126
View File
@@ -1,126 +0,0 @@
name: build_docker
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
build_docker:
name: Build Docker
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: xhofe/alist
tags: |
type=schedule
type=ref,event=branch
type=ref,event=tag
type=ref,event=pr
type=raw,value=beta,enable={{is_default_branch}}
- name: Docker meta with ffmpeg
id: meta-ffmpeg
uses: docker/metadata-action@v5
with:
images: xhofe/alist
flavor: |
suffix=-ffmpeg
tags: |
type=schedule
type=ref,event=branch
type=ref,event=tag
type=ref,event=pr
type=raw,value=beta,enable={{is_default_branch}}
- uses: actions/setup-go@v5
with:
go-version: 'stable'
- name: Cache Musl
id: cache-musl
uses: actions/cache@v4
with:
path: build/musl-libs
key: docker-musl-libs-v2
- name: Download Musl Library
if: steps.cache-musl.outputs.cache-hit != 'true'
run: bash build.sh prepare docker-multiplatform
- name: Build go binary
run: bash build.sh dev docker-multiplatform
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
if: github.event_name == 'push'
uses: docker/login-action@v3
with:
username: xhofe
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile.ci
push: ${{ github.event_name == 'push' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/386,linux/arm/v6,linux/s390x,linux/ppc64le,linux/riscv64
- name: Build and push with ffmpeg
id: docker_build_ffmpeg
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile.ci
push: ${{ github.event_name == 'push' }}
tags: ${{ steps.meta-ffmpeg.outputs.tags }}
labels: ${{ steps.meta-ffmpeg.outputs.labels }}
build-args: INSTALL_FFMPEG=true
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/386,linux/arm/v6,linux/s390x,linux/ppc64le,linux/riscv64
build_docker_with_aria2:
needs: build_docker
name: Build docker with aria2
runs-on: ubuntu-latest
if: github.event_name == 'push'
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
repository: alist-org/with_aria2
ref: main
persist-credentials: false
fetch-depth: 0
- name: Commit
run: |
git config --local user.email "bot@nn.ci"
git config --local user.name "IlaBot"
git commit --allow-empty -m "Trigger build for ${{ github.sha }}"
- name: Push commit
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.MY_TOKEN }}
branch: main
repository: alist-org/with_aria2
+6 -3
View File
@@ -1,17 +1,20 @@
name: auto changelog
name: Release Automatic changelog
on:
push:
tags:
- 'v*'
permissions:
contents: write
jobs:
changelog:
name: Create Release
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
@@ -21,4 +24,4 @@ jobs:
- run: npx changelogithub # or changelogithub@0.12 if ensure the stable result
env:
GITHUB_TOKEN: ${{secrets.MY_TOKEN}}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
+215
View File
@@ -0,0 +1,215 @@
name: Container Registry Cleanup
permissions:
contents: read
packages: write
on:
workflow_dispatch:
inputs:
package:
description: 'The name of the package to clean up'
required: true
default: 'openlist-git'
owner:
description: 'The owner of the package (user or organization)'
required: false
default: 'openlistteam'
older_than:
description: 'Delete untagged images older than this many days'
required: false
default: '-1'
untagged_timestamp_tolerance:
description: 'Tolerance in milliseconds for untagged images close to tagged ones'
required: false
# We do this because multi-arch docker containers will be pushed as separate untagged images
# to the container registry and GitHub cannot recognize them as part of a tagged image.
# Setting this option large enough prevents accidental deletion of one of these images.
# Here we set it to 10 seconds
default: '10000'
token:
description: 'GitHub token with permissions to delete packages (leave empty to use default GITHUB_TOKEN)'
required: false
default: ''
jobs:
cleanup:
runs-on: ubuntu-slim
steps:
- name: Check inputs and tools
id: setup
shell: bash
run: |
PACKAGE="${{ github.event.inputs.package || 'openlist-git' }}"
OLDER="${{ github.event.inputs.older_than || '-1' }}"
TOLERANCE_VAL="${{ github.event.inputs.untagged_timestamp_tolerance || '10000' }}"
TOKEN_INPUT="${{ github.event.inputs.token || '' }}"
OWNER="${{ github.event.inputs.owner || 'openlistteam' }}"
echo "package_name=$PACKAGE" >> "$GITHUB_OUTPUT"
echo "older_than=$OLDER" >> "$GITHUB_OUTPUT"
echo "tolerance=$TOLERANCE_VAL" >> "$GITHUB_OUTPUT"
echo "owner=$OWNER" >> "$GITHUB_OUTPUT"
if [[ -z "$TOKEN_INPUT" ]]; then
echo "::notice:: No token provided, using GITHUB_TOKEN instead."
echo "token=${{ secrets.GITHUB_TOKEN }}" >> "$GITHUB_OUTPUT"
else
echo "::add-mask::$TOKEN_INPUT"
echo "token=$TOKEN_INPUT" >> "$GITHUB_OUTPUT"
fi
if [[ -z "$PACKAGE" || -z "$OWNER" || ( -z "$TOKEN_INPUT" && -z "${{ secrets.GITHUB_TOKEN }}" ) ]]; then
echo "::error:: Missing required inputs (package, token, or owner context)."
exit 1
fi
command -v curl >/dev/null 2>&1 || { echo "::error::curl is required but not installed."; exit 1; }
command -v jq >/dev/null 2>&1 || { echo "::error::jq is required but not installed."; exit 1; }
- name: Determine owner type (user or organization)
id: owner_type
shell: bash
run: |
OWNER="${{ steps.setup.outputs.owner }}"
TOKEN="${{ steps.setup.outputs.token }}"
TYPE=$(curl -s -H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/users/${OWNER}" | jq -r '.type')
if [[ "$TYPE" == "Organization" ]]; then
OWNER_PATH="orgs"
else
OWNER_PATH="users"
fi
echo "owner_path=$OWNER_PATH" >> "$GITHUB_OUTPUT"
echo "Detected owner type: $TYPE (using /${OWNER_PATH}/)"
- name: Access all versions from GitHub
id: fetch
shell: bash
run: |
PACKAGE_NAME="${{ steps.setup.outputs.package_name }}"
OWNER="${{ steps.setup.outputs.owner }}"
TOKEN="${{ steps.setup.outputs.token }}"
OWNER_PATH="${{ steps.owner_type.outputs.owner_path }}"
BASE_URL="https://api.github.com/${OWNER_PATH}/${OWNER}/packages/container/${PACKAGE_NAME}/versions"
URL="${BASE_URL}?per_page=100"
TEMP_FILE="/tmp/all_versions.ndjson"
> "$TEMP_FILE"
PAGE=1
while [[ -n "$URL" && $PAGE -le 10 ]]; do
echo "Fetching: $URL"
curl -s -H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-D headers.txt \
"$URL" > page.json
jq -c '.[]' page.json >> "$TEMP_FILE"
URL=$(grep -i '^link:' headers.txt | grep -o '<[^>]*>;\s*rel="next"' | sed 's/<\(.*\)>.*/\1/' || true)
PAGE=$((PAGE + 1))
done
rm -f headers.txt page.json
echo "temp_file=$TEMP_FILE" >> "$GITHUB_OUTPUT"
- name: Filter untagged versions
id: filter
shell: bash
run: |
OLDER_THAN="${{ steps.setup.outputs.older_than }}"
TOLERANCE="${{ steps.setup.outputs.tolerance }}"
TEMP_FILE="${{ steps.fetch.outputs.temp_file }}"
TO_DELETE=$(jq -c -s \
--arg older_than "$OLDER_THAN" \
--arg tolerance "$TOLERANCE" \
'
def abs: if . < 0 then -. else . end;
def to_ms: sub("\\.[0-9]+Z$"; "Z") | strptime("%Y-%m-%dT%H:%M:%SZ") | mktime * 1000;
. as $all |
($older_than | tonumber) as $older_than_val |
($tolerance | tonumber) as $tolerance_val |
now as $now |
(if $older_than_val > 0 then ($now - ($older_than_val * 86400)) * 1000 else 0 end) as $cutoff_ms |
[ $all[] | select((.metadata.container.tags // []) | length > 0) | .created_at | to_ms ] as $tagged_times |
$all[] |
select((.metadata.container.tags // []) | length == 0) |
. as $item |
(.created_at | to_ms) as $created_ms |
(if $older_than_val > 0 then $created_ms < $cutoff_ms else true end) as $pass_age |
(if $tolerance_val <= 0 then true
else [ $tagged_times[] | select(($created_ms - .) | abs < $tolerance_val) ] | length == 0
end) as $pass_tolerance |
select($pass_age and $pass_tolerance) |
{id, name}
' "$TEMP_FILE")
rm -f "$TEMP_FILE"
if [[ -z "$TO_DELETE" ]]; then
DELETE_COUNT=0
else
DELETE_COUNT=$(echo "$TO_DELETE" | wc -l | tr -d ' ')
fi
echo "Found $DELETE_COUNT untagged images no longer necessary"
{
echo 'to_delete<<EOF'
echo "$TO_DELETE"
echo 'EOF'
} >> "$GITHUB_OUTPUT"
echo "delete_count=$DELETE_COUNT" >> "$GITHUB_OUTPUT"
- name: Delete untagged versions
id: delete
shell: bash
run: |
PACKAGE_NAME="${{ steps.setup.outputs.package_name }}"
OWNER="${{ steps.setup.outputs.owner }}"
TOKEN="${{ steps.setup.outputs.token }}"
OWNER_PATH="${{ steps.owner_type.outputs.owner_path }}"
DELETE_COUNT="${{ steps.filter.outputs.delete_count }}"
TO_DELETE='${{ steps.filter.outputs.to_delete }}'
if [[ "$DELETE_COUNT" -gt 0 && -n "$TO_DELETE" ]]; then
while IFS= read -r item; do
[[ -z "$item" ]] && continue
# $item 是完整的单行 JSON,如 {"id":123,"name":"sha256:..."}
ID=$(echo "$item" | jq -r '.id')
NAME=$(echo "$item" | jq -r '.name')
DELETE_URL="https://api.github.com/${OWNER_PATH}/${OWNER}/packages/container/${PACKAGE_NAME}/versions/${ID}"
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
"$DELETE_URL")
if [[ "$HTTP_CODE" == "204" ]]; then
echo "Deleted untagged container image '${NAME}'"
else
echo "::warning:: Failed to delete ${NAME} (ID: ${ID}). HTTP Status: ${HTTP_CODE}"
fi
done <<< "$TO_DELETE"
else
echo "No images to delete."
fi
echo "Cleanup completed."
@@ -1,22 +0,0 @@
name: Close need info
on:
schedule:
- cron: "0 0 */1 * *"
workflow_dispatch:
jobs:
close-need-info:
runs-on: ubuntu-latest
steps:
- name: close-issues
uses: actions-cool/issues-helper@v3
with:
actions: 'close-issues'
token: ${{ secrets.GITHUB_TOKEN }}
labels: 'question'
inactive-day: 3
close-reason: 'not_planned'
body: |
Hello @${{ github.event.issue.user.login }}, this issue was closed due to no activities in 3 days.
你好 @${{ github.event.issue.user.login }},此issue因超过3天未回复被关闭。
-21
View File
@@ -1,21 +0,0 @@
name: Close inactive
on:
schedule:
- cron: "0 0 */7 * *"
workflow_dispatch:
jobs:
close-inactive:
runs-on: ubuntu-latest
steps:
- name: close-issues
uses: actions-cool/issues-helper@v3
with:
actions: 'close-issues'
token: ${{ secrets.GITHUB_TOKEN }}
labels: 'stale'
inactive-day: 8
close-reason: 'not_planned'
body: |
Hello @${{ github.event.issue.user.login }}, this issue was closed due to inactive more than 52 days. You can reopen or recreate it if you think it should continue. Thank you for your contributions again.
+75
View File
@@ -0,0 +1,75 @@
name: Issue Auto Reply
on:
issues:
types: [opened]
permissions:
issues: write
jobs:
auto-reply:
runs-on: ubuntu-latest
steps:
- name: Check issue for unchecked tasks and reply
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
if (context.payload.issue.title.startsWith('[Announcements]')) return;
const titleNotEdited = /(请修改标题|Please modify the title)/i.test(context.payload.issue.title);
const issueBody = context.payload.issue.body || "";
const aiSection = issueBody.match(/^### (AI生成内容|AI Generated Content)\r?\n([\s\S]*?)(?=^### |$(?![\s\S]))/m);
const aiOptionsPattern = aiSection?.[1] === 'AI生成内容'
? /^\s*- \[([ xX])\] 我使用了AI工具生成此内容\r?\n- \[([ xX])\] 我没有使用AI工具生成此内容\s*$/
: /^\s*- \[([ xX])\] I used AI tools to generate this content\r?\n- \[([ xX])\] I did not use AI tools to generate this content\s*$/;
const aiOptions = (aiSection?.[2] || '').match(aiOptionsPattern);
const validAiDisclosure = aiOptions !== null && (aiOptions[1] !== ' ') !== (aiOptions[2] !== ' ');
const aiModelSection = issueBody.match(/^### (AI模型是|AI model used)\r?\n([\s\S]*?)(?=^### |$(?![\s\S]))/m);
const aiModel = (aiModelSection?.[2] || '').trim();
const missingAiModel = validAiDisclosure && aiOptions[1] !== ' ' && (aiModel === '' || aiModel === '_No response_');
const confirmNotRead = /- \[[xX]\] (?:我没有阅读这个清单|I have not read these checkboxes)/.test(issueBody);
const closeIssue = titleNotEdited || confirmNotRead || !validAiDisclosure || missingAiModel;
let comment;
if (titleNotEdited) {
comment = `⚠️ 请修改标题以更好地描述您的问题或需求,并删除示例提示。当前 Issue 将被自动关闭并锁定。如需继续提交,请创建新的 Issue。
⚠️ Please modify the title to better describe your issue or request, and remove the example prompt. This issue will be automatically closed and locked. If you wish to proceed, please create a new issue.
`;
} else if (confirmNotRead || !validAiDisclosure || missingAiModel) {
comment = `⚠️ 你的 Issue 不符合提交规则。请先阅读相关规范后再重新提交。当前 Issue 将被自动关闭并锁定。如需继续提交,请确认已了解规则后创建新的 Issue。
⚠️ Your issue does not comply with the submission rules. Please read the guidelines before submitting again. This issue will be automatically closed and locked. If you wish to proceed, please confirm that you have reviewed the rules before creating a new issue.
`;
} else if (/- \[ \] (?!我没有阅读这个清单|I have not read these checkboxes)/.test(issueBody.replace(aiSection[0], ''))) {
comment = `感谢您联系OpenList。我们会尽快回复您。
Thanks for contacting OpenList. We will reply to you as soon as possible.
由于您提出的 Issue 中包含部分未确认的项目,为了更好地管理项目,在人工审核后可能会直接关闭此问题。
如果您能确认并补充相关未确认项目的信息,欢迎随时重新提交。我们会及时关注并处理。感谢您的理解与支持!
Since your issue contains some unchecked tasks, it may be closed after manual review.
If you can confirm and provide information for the unchecked tasks, feel free to resubmit.
We will pay attention and handle it in a timely manner.
感谢您的理解与支持!
Thank you for your understanding and support!
`;
} else {
return;
}
await github.rest.issues.createComment({
...context.repo,
issue_number: context.issue.number,
body: comment
});
if (closeIssue) {
await github.rest.issues.update({
...context.repo,
issue_number: context.issue.number,
state: 'closed',
state_reason: 'not_planned',
labels: ['invalid']
});
await github.rest.issues.lock({
...context.repo,
issue_number: context.issue.number
});
}
-25
View File
@@ -1,25 +0,0 @@
name: Issue Duplicate
on:
issues:
types: [labeled]
jobs:
create-comment:
runs-on: ubuntu-latest
if: github.event.label.name == 'duplicate'
steps:
- name: Create comment
uses: actions-cool/issues-helper@v3
with:
actions: 'create-comment'
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
body: |
Hello @${{ github.event.issue.user.login }}, your issue is a duplicate and will be closed.
你好 @${{ github.event.issue.user.login }},你的issue是重复的,将被关闭。
- name: Close issue
uses: actions-cool/issues-helper@v3
with:
actions: 'close-issue'
token: ${{ secrets.GITHUB_TOKEN }}
-25
View File
@@ -1,25 +0,0 @@
name: Issue Invalid
on:
issues:
types: [labeled]
jobs:
create-comment:
runs-on: ubuntu-latest
if: github.event.label.name == 'invalid'
steps:
- name: Create comment
uses: actions-cool/issues-helper@v3
with:
actions: 'create-comment'
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
body: |
Hello @${{ github.event.issue.user.login }}, your issue is invalid and will be closed.
你好 @${{ github.event.issue.user.login }},你的issue无效,将被关闭。
- name: Close issue
uses: actions-cool/issues-helper@v3
with:
actions: 'close-issue'
token: ${{ secrets.GITHUB_TOKEN }}
-17
View File
@@ -1,17 +0,0 @@
name: Remove working label when issue closed
on:
issues:
types: [closed]
jobs:
rm-working:
runs-on: ubuntu-latest
steps:
- name: Remove working label
uses: actions-cool/issues-helper@v3
with:
actions: 'remove-labels'
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
labels: 'working,pr-welcome'
-20
View File
@@ -1,20 +0,0 @@
name: Issue Question
on:
issues:
types: [labeled]
jobs:
create-comment:
runs-on: ubuntu-latest
if: github.event.label.name == 'question'
steps:
- name: Create comment
uses: actions-cool/issues-helper@v3.6.0
with:
actions: 'create-comment'
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
body: |
Hello @${{ github.event.issue.user.login }}, please input issue by template and add detail. Issues labeled by `question` will be closed if no activities in 3 days.
你好 @${{ github.event.issue.user.login }},请按照issue模板填写, 并详细说明问题/日志记录/复现步骤/复现链接/实现思路或提供更多信息等, 3天内未回复issue自动关闭。
-19
View File
@@ -1,19 +0,0 @@
name: Issues Similarity Analysis
on:
issues:
types: [opened, edited]
jobs:
similarity-analysis:
runs-on: ubuntu-latest
steps:
- name: analysis
uses: actions-cool/issues-similarity-analysis@v1
with:
filter-threshold: 0.5
comment-title: '### See'
comment-body: '${index}. ${similarity} #${number}'
show-footer: false
show-mentioned: true
since-days: 730
-13
View File
@@ -1,13 +0,0 @@
name: Translation Helper
on:
pull_request_target:
types: [opened]
issues:
types: [opened]
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: actions-cool/translation-helper@v1.2.0
-25
View File
@@ -1,25 +0,0 @@
name: Issue Wontfix
on:
issues:
types: [labeled]
jobs:
lock-issue:
runs-on: ubuntu-latest
if: github.event.label.name == 'wontfix'
steps:
- name: Create comment
uses: actions-cool/issues-helper@v3
with:
actions: 'create-comment'
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
body: |
Hello @${{ github.event.issue.user.login }}, this issue will not be worked on and will be closed.
你好 @${{ github.event.issue.user.login }},这不会被处理,将被关闭。
- name: Close issue
uses: actions-cool/issues-helper@v3
with:
actions: 'close-issue'
token: ${{ secrets.GITHUB_TOKEN }}
+34
View File
@@ -0,0 +1,34 @@
name: PR Title Check
on:
pull_request_target:
types: [opened]
permissions:
pull-requests: write
jobs:
pr-title-check:
runs-on: ubuntu-latest
steps:
- name: Check PR title for required prefix and comment
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const title = context.payload.pull_request.title;
if (/^(feat|docs|fix|style|refactor|chore)\(.+?\)!?: /i.test(title)) return;
const comment = `⚠️ PR 标题需以 \`feat(): \`, \`docs(): \`, \`fix(): \`, \`style(): \`, \`refactor(): \`, \`chore(): \` 其中之一开头,例如:\`feat(component): 新增功能\`。
⚠️ The PR title must start with \`feat(): \`, \`docs(): \`, \`fix(): \`, \`style(): \`, or \`refactor(): \`, \`chore(): \`. For example: \`feat(component): add new feature\`.
如果跨多个组件,请使用主要组件作为前缀,并在标题中枚举、描述中说明。
If it spans multiple components, use the main component as the prefix and enumerate in the title, describe in the body.
如果是破坏性变更,请在类型后添加 \`!\`,例如 \`feat(component)!: 破坏性变更\`。
For breaking changes, add \`!\` after the type, e.g., \`feat(component)!: breaking change\`.
`;
await github.rest.issues.createComment({
...context.repo,
issue_number: context.issue.number,
body: comment
});
+49 -46
View File
@@ -1,36 +1,61 @@
name: release
name: Release builds
on:
release:
types: [ published ]
permissions:
contents: write
jobs:
release:
strategy:
matrix:
platform: [ ubuntu-latest ]
go-version: [ '1.21' ]
name: Release
runs-on: ${{ matrix.platform }}
# Set release to prerelease first
prerelease:
name: Set Prerelease
runs-on: ubuntu-latest
steps:
- name: Prerelease
uses: irongut/EditRelease@v1.2.0
uses: irongut/EditRelease@ccf529ad26dddf9996e7dd0f24ca5da4ea507cc2 # v1.2.0
with:
token: ${{ secrets.MY_TOKEN }}
token: ${{ secrets.GITHUB_TOKEN }}
id: ${{ github.event.release.id }}
prerelease: true
- name: Setup Go
uses: actions/setup-go@v5
# Main release job for all platforms
release:
needs: prerelease
strategy:
matrix:
build-type: [ 'standard', 'lite' ]
target-platform: [ '', 'android', 'freebsd', 'linux_musl', 'linux_musl_arm' ]
name: Release ${{ matrix.target-platform && format('{0} ', matrix.target-platform) || '' }}${{ matrix.build-type == 'lite' && 'Lite' || '' }}
runs-on: ubuntu-latest
steps:
- name: Free Disk Space (Ubuntu)
if: matrix.target-platform == ''
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # main
with:
go-version: ${{ matrix.go-version }}
tool-cache: false
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: '1.27.1'
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
fetch-depth: 1
fetch-tags: true
- name: Install dependencies
if: matrix.target-platform == ''
run: |
sudo snap install zig --classic --beta
docker pull crazymax/xgo:latest
@@ -39,37 +64,15 @@ jobs:
- name: Build
run: |
bash build.sh release
bash build.sh release ${{ matrix.build-type == 'lite' && 'lite' || '' }} ${{ matrix.target-platform }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FRONTEND_REPO: ${{ vars.FRONTEND_REPO }}
- name: Upload assets
uses: softprops/action-gh-release@v2
with:
files: build/compress/*
prerelease: false
release_desktop:
needs: release
name: Release desktop
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
repository: alist-org/desktop-release
ref: main
persist-credentials: false
fetch-depth: 0
- name: Add tag
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git config --local user.email "bot@nn.ci"
git config --local user.name "IlaBot"
version=$(wget -qO- -t1 -T2 "https://api.github.com/repos/alist-org/alist/releases/latest" | grep "tag_name" | head -n 1 | awk -F ":" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g')
git tag -a $version -m "release $version"
- name: Push tags
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.MY_TOKEN }}
branch: main
repository: alist-org/desktop-release
for file in build/compress/*; do
gh release upload "${{ github.event.release.tag_name }}" "$file" --clobber
done
-34
View File
@@ -1,34 +0,0 @@
name: release_android
on:
release:
types: [ published ]
jobs:
release_android:
strategy:
matrix:
platform: [ ubuntu-latest ]
go-version: [ '1.21' ]
name: Release
runs-on: ${{ matrix.platform }}
steps:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build
run: |
bash build.sh release android
- name: Upload assets
uses: softprops/action-gh-release@v2
with:
files: build/compress/*
+245 -66
View File
@@ -1,25 +1,57 @@
name: release_docker
name: Release builds (Docker)
on:
workflow_dispatch:
inputs:
manual_tag:
description: 'Tag name (like v0.1.0). Required if as_latest is true.'
required: false
type: string
as_latest:
description: 'Tag as latest?'
required: true
default: 'false'
type: choice
options:
- 'true'
- 'false'
push:
tags:
- 'v*'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
DOCKERHUB_ORG_NAME: ${{ vars.DOCKERHUB_ORG_NAME || 'openlistteam' }}
GHCR_ORG_NAME: ${{ vars.GHCR_ORG_NAME || 'openlistteam' }}
IMAGE_NAME: openlist-git
IMAGE_NAME_DOCKERHUB: openlist
REGISTRY: ghcr.io
ARTIFACT_NAME: 'binaries_docker_release'
ARTIFACT_NAME_LITE: 'binaries_docker_release_lite'
RELEASE_PLATFORMS: 'linux/amd64,linux/arm64,linux/arm/v7,linux/386,linux/arm/v6,linux/ppc64le,linux/riscv64,linux/loong64' ### Temporarily disable Docker builds for linux/s390x architectures for unknown reasons.
IMAGE_PUSH: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }}
permissions:
packages: write
jobs:
release_docker:
name: Release Docker
build_binary:
name: Build Binaries for Docker Release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: actions/setup-go@v5
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: 'stable'
go-version: '1.27'
- name: Cache Musl
id: cache-musl
uses: actions/cache@v4
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: build/musl-libs
key: docker-musl-libs-v2
@@ -27,82 +59,229 @@ jobs:
- name: Download Musl Library
if: steps.cache-musl.outputs.cache-hit != 'true'
run: bash build.sh prepare docker-multiplatform
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build go binary
- name: Build go binary (release)
run: bash build.sh release docker-multiplatform
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FRONTEND_REPO: ${{ vars.FRONTEND_REPO }}
- name: Upload artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: ${{ env.ARTIFACT_NAME }}
overwrite: true
path: |
build/
!build/*.tgz
!build/musl-libs/**
build_binary_lite:
name: Build Binaries for Docker Release (Lite)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: '1.27.1'
- name: Cache Musl
id: cache-musl
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: build/musl-libs
key: docker-musl-libs-v2
- name: Download Musl Library
if: steps.cache-musl.outputs.cache-hit != 'true'
run: bash build.sh prepare lite docker-multiplatform
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build go binary (release)
run: bash build.sh release lite docker-multiplatform
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FRONTEND_REPO: ${{ vars.FRONTEND_REPO }}
- name: Upload artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: ${{ env.ARTIFACT_NAME_LITE }}
overwrite: true
path: |
build/
!build/*.tgz
!build/musl-libs/**
release_docker:
needs: build_binary
name: Release Docker image
runs-on: ubuntu-latest
strategy:
matrix:
image: ["latest", "ffmpeg", "aria2", "aio"]
include:
- image: "latest"
base_image_tag: "base"
build_arg: ""
tag_favor: ""
- image: "ffmpeg"
base_image_tag: "ffmpeg"
build_arg: INSTALL_FFMPEG=true
tag_favor: "suffix=-ffmpeg,onlatest=true"
- image: "aria2"
base_image_tag: "aria2"
build_arg: INSTALL_ARIA2=true
tag_favor: "suffix=-aria2,onlatest=true"
- image: "aio"
base_image_tag: "aio"
build_arg: |
INSTALL_FFMPEG=true
INSTALL_ARIA2=true
tag_favor: "suffix=-aio,onlatest=true"
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: ${{ env.ARTIFACT_NAME }}
path: 'build/'
- name: Set up QEMU
uses: docker/setup-qemu-action@1f40c72289eff860ee54a304f1438e3cff362e0a # v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4
- name: Login to GitHub Container Registry
if: env.IMAGE_PUSH == 'true'
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to DockerHub Container Registry
if: env.IMAGE_PUSH == 'true'
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
with:
username: ${{ vars.DOCKERHUB_ORG_NAME_BACKUP || env.DOCKERHUB_ORG_NAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6
with:
images: xhofe/alist
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: xhofe
password: ${{ secrets.DOCKERHUB_TOKEN }}
images: |
${{ env.REGISTRY }}/${{ env.GHCR_ORG_NAME }}/${{ env.IMAGE_NAME }}
${{ env.DOCKERHUB_ORG_NAME }}/${{ env.IMAGE_NAME_DOCKERHUB }}
tags: >
${{ github.event_name == 'workflow_dispatch'
&& format('type=raw,value={0}', github.event.inputs.manual_tag)
|| format('type=raw,value={0}', github.ref_name) }}
flavor: |
latest=${{ github.event_name == 'push' || github.event.inputs.as_latest == 'true' }}
${{ matrix.tag_favor }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v6
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
with:
context: .
file: Dockerfile.ci
push: true
push: ${{ env.IMAGE_PUSH == 'true' }}
build-args: |
BASE_IMAGE_TAG=${{ matrix.base_image_tag }}
${{ matrix.build_arg }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/386,linux/arm/v6,linux/s390x,linux/ppc64le,linux/riscv64
platforms: ${{ env.RELEASE_PLATFORMS }}
- name: Docker meta with ffmpeg
id: meta-ffmpeg
uses: docker/metadata-action@v5
release_docker_lite:
needs: build_binary_lite
name: Release Docker image (Lite)
runs-on: ubuntu-latest
strategy:
matrix:
image: ["latest", "ffmpeg", "aria2", "aio"]
include:
- image: "latest"
base_image_tag: "base"
build_arg: ""
tag_favor: "suffix=-lite,onlatest=true"
- image: "ffmpeg"
base_image_tag: "ffmpeg"
build_arg: INSTALL_FFMPEG=true
tag_favor: "suffix=-lite-ffmpeg,onlatest=true"
- image: "aria2"
base_image_tag: "aria2"
build_arg: INSTALL_ARIA2=true
tag_favor: "suffix=-lite-aria2,onlatest=true"
- image: "aio"
base_image_tag: "aio"
build_arg: |
INSTALL_FFMPEG=true
INSTALL_ARIA2=true
tag_favor: "suffix=-lite-aio,onlatest=true"
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
images: xhofe/alist
name: ${{ env.ARTIFACT_NAME_LITE }}
path: 'build/'
- name: Set up QEMU
uses: docker/setup-qemu-action@1f40c72289eff860ee54a304f1438e3cff362e0a # v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4
- name: Login to GitHub Container Registry
if: env.IMAGE_PUSH == 'true'
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to DockerHub Container Registry
if: env.IMAGE_PUSH == 'true'
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
with:
username: ${{ vars.DOCKERHUB_ORG_NAME_BACKUP || env.DOCKERHUB_ORG_NAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Docker meta
id: meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6
with:
images: |
${{ env.REGISTRY }}/${{ env.GHCR_ORG_NAME }}/${{ env.IMAGE_NAME }}
${{ env.DOCKERHUB_ORG_NAME }}/${{ env.IMAGE_NAME_DOCKERHUB }}
tags: >
${{ github.event_name == 'workflow_dispatch'
&& format('type=raw,value={0}', github.event.inputs.manual_tag)
|| format('type=raw,value={0}', github.ref_name) }}
flavor: |
latest=true
suffix=-ffmpeg,onlatest=true
- name: Build and push with ffmpeg
id: docker_build_ffmpeg
uses: docker/build-push-action@v6
latest=${{ github.event_name == 'push' || github.event.inputs.as_latest == 'true' }}
${{ matrix.tag_favor }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
with:
context: .
file: Dockerfile.ci
push: true
tags: ${{ steps.meta-ffmpeg.outputs.tags }}
labels: ${{ steps.meta-ffmpeg.outputs.labels }}
build-args: INSTALL_FFMPEG=true
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/386,linux/arm/v6,linux/s390x,linux/ppc64le,linux/riscv64
release_docker_with_aria2:
needs: release_docker
name: Release docker with aria2
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
repository: alist-org/with_aria2
ref: main
persist-credentials: false
fetch-depth: 0
- name: Add tag
run: |
git config --local user.email "bot@nn.ci"
git config --local user.name "IlaBot"
git tag -a ${{ github.ref_name }} -m "release ${{ github.ref_name }}"
- name: Push tags
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.MY_TOKEN }}
branch: main
repository: alist-org/with_aria2
push: ${{ env.IMAGE_PUSH == 'true' }}
build-args: |
BASE_IMAGE_TAG=${{ matrix.base_image_tag }}
${{ matrix.build_arg }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: ${{ env.RELEASE_PLATFORMS }}
-35
View File
@@ -1,35 +0,0 @@
name: release_freebsd
on:
release:
types: [ published ]
jobs:
release_freebsd:
strategy:
matrix:
platform: [ ubuntu-latest ]
go-version: [ '1.21' ]
name: Release
runs-on: ${{ matrix.platform }}
steps:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build
run: |
bash build.sh release freebsd
- name: Upload assets
uses: softprops/action-gh-release@v2
with:
tag_name: dev
files: build/compress/*
-34
View File
@@ -1,34 +0,0 @@
name: release_linux_musl
on:
release:
types: [ published ]
jobs:
release_linux_musl:
strategy:
matrix:
platform: [ ubuntu-latest ]
go-version: [ '1.21' ]
name: Release
runs-on: ${{ matrix.platform }}
steps:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build
run: |
bash build.sh release linux_musl
- name: Upload assets
uses: softprops/action-gh-release@v2
with:
files: build/compress/*
@@ -1,34 +0,0 @@
name: release_linux_musl_arm
on:
release:
types: [ published ]
jobs:
release_linux_musl_arm:
strategy:
matrix:
platform: [ ubuntu-latest ]
go-version: [ '1.21' ]
name: Release
runs-on: ${{ matrix.platform }}
steps:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build
run: |
bash build.sh release linux_musl_arm
- name: Upload assets
uses: softprops/action-gh-release@v2
with:
files: build/compress/*
+38
View File
@@ -0,0 +1,38 @@
name: Sync to Gitee
on:
push:
branches:
- main
workflow_dispatch:
jobs:
sync:
runs-on: ubuntu-latest
name: Sync GitHub to Gitee
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.GITEE_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan gitee.com >> ~/.ssh/known_hosts
- name: Create single commit and push
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
# Create a new branch
git checkout --orphan new-main
git add .
git commit -m "Sync from GitHub: $(date)"
# Add Gitee remote and force push
git remote add gitee ${{ vars.GITEE_REPO_URL }}
git push --force gitee new-main:main
+150
View File
@@ -0,0 +1,150 @@
name: Beta Release (Docker)
on:
workflow_dispatch:
push:
branches:
- main
pull_request:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
DOCKERHUB_ORG_NAME: ${{ vars.DOCKERHUB_ORG_NAME || 'openlistteam' }}
GHCR_ORG_NAME: ${{ vars.GHCR_ORG_NAME || 'openlistteam' }}
IMAGE_NAME: openlist-git
IMAGE_NAME_DOCKERHUB: openlist
REGISTRY: ghcr.io
ARTIFACT_NAME: 'binaries_docker_release'
RELEASE_PLATFORMS: 'linux/amd64,linux/arm64,linux/arm/v7,linux/386,linux/arm/v6,linux/ppc64le,linux/riscv64,linux/loong64' ### Temporarily disable Docker builds for linux/s390x architectures for unknown reasons.
IMAGE_PUSH: ${{ github.event_name == 'push' }}
IMAGE_TAGS_BETA: |
type=ref,event=pr
type=raw,value=beta,enable={{is_default_branch}}
jobs:
build_binary:
name: Build Binaries for Docker Release (Beta)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: '1.27.1'
- name: Cache Musl
id: cache-musl
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: build/musl-libs
key: docker-musl-libs-v2
- name: Download Musl Library
if: steps.cache-musl.outputs.cache-hit != 'true'
run: bash build.sh prepare docker-multiplatform
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build go binary (beta)
run: bash build.sh beta docker-multiplatform
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FRONTEND_REPO: ${{ vars.FRONTEND_REPO }}
- name: Upload artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: ${{ env.ARTIFACT_NAME }}
overwrite: true
path: |
build/
!build/*.tgz
!build/musl-libs/**
release_docker:
needs: build_binary
name: Release Docker image (Beta)
runs-on: ubuntu-latest
permissions:
packages: write
strategy:
matrix:
image: ["latest", "ffmpeg", "aria2", "aio"]
include:
- image: "latest"
base_image_tag: "base"
build_arg: ""
tag_favor: ""
- image: "ffmpeg"
base_image_tag: "ffmpeg"
build_arg: INSTALL_FFMPEG=true
tag_favor: "suffix=-ffmpeg,onlatest=true"
- image: "aria2"
base_image_tag: "aria2"
build_arg: INSTALL_ARIA2=true
tag_favor: "suffix=-aria2,onlatest=true"
- image: "aio"
base_image_tag: "aio"
build_arg: |
INSTALL_FFMPEG=true
INSTALL_ARIA2=true
tag_favor: "suffix=-aio,onlatest=true"
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: ${{ env.ARTIFACT_NAME }}
path: 'build/'
- name: Set up QEMU
uses: docker/setup-qemu-action@1f40c72289eff860ee54a304f1438e3cff362e0a # v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4
- name: Login to GitHub Container Registry
if: env.IMAGE_PUSH == 'true'
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to DockerHub Container Registry
if: env.IMAGE_PUSH == 'true'
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
with:
username: ${{ vars.DOCKERHUB_ORG_NAME_BACKUP || env.DOCKERHUB_ORG_NAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Docker meta
id: meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6
with:
images: |
${{ env.REGISTRY }}/${{ env.GHCR_ORG_NAME }}/${{ env.IMAGE_NAME }}
${{ env.DOCKERHUB_ORG_NAME }}/${{ env.IMAGE_NAME_DOCKERHUB }}
tags: ${{ env.IMAGE_TAGS_BETA }}
flavor: |
${{ matrix.tag_favor }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
with:
context: .
file: Dockerfile.ci
push: ${{ env.IMAGE_PUSH == 'true' }}
build-args: |
BASE_IMAGE_TAG=${{ matrix.base_image_tag }}
${{ matrix.build_arg }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: ${{ env.RELEASE_PLATFORMS }}
@@ -0,0 +1,53 @@
name: Trigger OpenWRT Update
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
tag:
description: 'Release tag to trigger update for'
required: true
type: string
jobs:
trigger-makefile-update:
runs-on: ubuntu-latest
steps:
- name: Trigger Makefile hash update
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
github-token: ${{ secrets.EXTERNAL_REPO_TOKEN_LUCI_APP_OPENLIST }}
script: |
const repository = process.env.REPOSITORY;
const [owner, repo] = repository.split('/');
await github.rest.repos.createDispatchEvent({
owner: owner,
repo: repo,
event_type: 'update-hashes',
client_payload: {
source_repository: process.env.SOURCE_REPOSITORY,
release_tag: process.env.RELEASE_TAG,
release_name: process.env.RELEASE_TAG,
release_url: process.env.RELEASE_URL,
triggered_by: process.env.ACTOR,
trigger_reason: process.env.EVENT_NAME
}
});
env:
REPOSITORY: ${{ vars.HOOK_REPO || 'OpenListTeam/OpenList-OpenWRT' }}
SOURCE_REPOSITORY: ${{ github.repository }}
RELEASE_TAG: ${{ inputs.tag || github.ref_name }}
RELEASE_URL: ${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ inputs.tag || github.ref_name }}
ACTOR: ${{ github.actor }}
EVENT_NAME: ${{ github.event_name }}
- name: Log trigger information
run: |
echo "🚀 Successfully triggered Makefile hash update"
echo "📦 Target repository: OpenListTeam/luci-app-openlist"
echo "🏷️ Tag: ${{ inputs.tag || github.ref_name }}"
echo "👤 Triggered by: ${{ github.actor }}"
echo "📅 Trigger time: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
+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
+60
View File
@@ -0,0 +1,60 @@
# Agent Instructions
## Issues
Before creating an issue, review the available issue templates in the `.github` directory.
When drafting the issue:
- Use the most appropriate template.
- Follow the template structure.
- Fill in all required sections.
- Remove sections that the template explicitly marks as optional or not applicable.
- Do not invent reproduction steps, logs, screenshots, or expected behavior.
## Pull Requests
Before creating a pull request, read `.github/PULL_REQUEST_TEMPLATE.md`.
When drafting the pull request:
- Follow the template structure.
- Use the title format required by the template.
- Fill in or remove each section according to the template guidance.
- Include testing details, or explain why testing was not run.
- Do not invent testing results.
- Do not claim validation, verification, or review steps that were not actually performed.
## Automated Contributions
Fully automated contributions are not considered equivalent to normal community participation.
A contribution may be considered fully automated if it is submitted through an automated agent, or if the submitting account participates in project discussions through an automated agent, without meaningful human review or intervention.
When making this determination, maintainers may consider the overall behavior of the account, including but not limited to disclosed agent usage, interaction patterns, response characteristics, and other available evidence. No single factor is determinative.
Maintainers reserve the right to accept, reject, modify, or reimplement any contribution independently of any action taken against the submitting account. Acceptance of a contribution does not imply acceptance of the submitting account or its contribution method. If an account is determined to be primarily operated through automated processes, we may need to restrict its future participation in contributions until that determination is rescinded.
## Git Commits
When creating commits, follow the repository `git-commit` skill rules:
- Use Conventional Commits title format: `type(scope): subject`.
- Allowed types: `feat`, `fix`, `refactor`, `perf`, `docs`, `style`, `test`, `build`, `ci`, `chore`, `revert`.
- Use a meaningful scope based on the main module, package, or feature.
- Write the subject in imperative mood and describe the actual change.
- Use a concise Markdown list in the commit body, with each item describing one key change.
- Do not invent changes that are not present in the diff.
- Do not describe behavior, refactors, fixes, or tests that are not reflected in the commit.
Include at most one `Co-authored-by` trailer that matches the AI assistant actually used to produce the change.
Examples:
- `Co-authored-by: Codex <267193182+codex@users.noreply.github.com>`
- `Co-authored-by: GitHub Copilot <copilot@github.com>`
- `Co-authored-by: Claude <81847+claude@users.noreply.github.com>`
If you are not one of the listed assistants, do not add a `Co-authored-by` trailer.
Instead, ask the human collaborator to provide the exact `Co-authored-by` trailer to use. Do not invent, infer, or generate one yourself.
+5 -5
View File
@@ -60,7 +60,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
i@nn.ci.
[Telegram Group](https://t.me/OpenListTeam).
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
@@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
@@ -116,7 +116,7 @@ the community.
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
<https://www.contributor-covenant.org/version/2/0/code_of_conduct.html>.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
@@ -124,5 +124,5 @@ enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
<https://www.contributor-covenant.org/faq>. Translations are available at
<https://www.contributor-covenant.org/translations>.
+75 -72
View File
@@ -2,106 +2,109 @@
## Setup your machine
`alist` is written in [Go](https://golang.org/) and [React](https://reactjs.org/).
`OpenList` is written in [Go](https://golang.org/) and [SolidJS](https://www.solidjs.com/).
Prerequisites:
- [git](https://git-scm.com)
- [Go 1.20+](https://golang.org/doc/install)
- [Go](https://golang.org/doc/install) version declared in [`go.mod`](./go.mod)
- [gcc](https://gcc.gnu.org/)
- [nodejs](https://nodejs.org/)
Clone `alist` and `alist-web` anywhere:
## Cloning a fork
Fork and clone `OpenList` and `OpenList-Frontend` anywhere:
```shell
$ git clone https://github.com/alist-org/alist.git
$ git clone --recurse-submodules https://github.com/alist-org/alist-web.git
git clone https://github.com/<your-username>/OpenList.git
git clone --recurse-submodules https://github.com/<your-username>/OpenList-Frontend.git
```
## Creating a branch
Create a new branch from the `main` branch, with an appropriate name.
```shell
git checkout -b <branch-name>
```
You should switch to the `main` branch for development.
## Preview your change
### backend
```shell
$ go run main.go
go run main.go
```
### frontend
```shell
$ pnpm dev
pnpm dev
```
## Add a new driver
Copy `drivers/template` folder and rename it, and follow the comments in it.
## Community and policies
By contributing, you agree to follow the repository's code of conduct and license terms.
- Code of conduct: [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md)
- License: [LICENSE](./LICENSE)
- Security issues: please report privately according to [SECURITY.md](./SECURITY.md)
If your contribution includes substantial AI-assisted content, disclose the tools used and the scope of assistance in the pull request.
## Create a commit
Commit messages should be well formatted, and to make that "standardized".
### Commit Message Format
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
format that includes a **type**, a **scope** and a **subject**:
Submit your pull request. For PR titles, follow [Conventional Commits](https://www.conventionalcommits.org).
```
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```
<https://github.com/OpenListTeam/OpenList/issues/376>
The **header** is mandatory and the **scope** of the header is optional.
Any line of the commit message cannot be longer than 100 characters! This allows the message to be easier
to read on GitHub as well as in various git tools.
### Revert
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header
of the reverted commit.
In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit
being reverted.
### Type
Must be one of the following:
* **feat**: A new feature
* **fix**: A bug fix
* **docs**: Documentation only changes
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing
semi-colons, etc)
* **refactor**: A code change that neither fixes a bug nor adds a feature
* **perf**: A code change that improves performance
* **test**: Adding missing or correcting existing tests
* **build**: Affects project builds or dependency modifications
* **revert**: Restore the previous commit
* **ci**: Continuous integration of related file modifications
* **chore**: Changes to the build process or auxiliary tools and libraries such as documentation
generation
* **release**: Release a new version
### Scope
The scope could be anything specifying place of the commit change. For example `$location`,
`$browser`, `$compile`, `$rootScope`, `ngHref`, `ngClick`, `ngView`, etc...
You can use `*` when the change affects more than a single scope.
### Subject
The subject contains succinct description of the change:
* use the imperative, present tense: "change" not "changed" nor "changes"
* don't capitalize first letter
* no dot (.) at the end
### Body
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
The body should include the motivation for the change and contrast this with previous behavior.
### Footer
The footer should contain any information about **Breaking Changes** and is also the place to
[reference GitHub issues that this commit closes](https://help.github.com/articles/closing-issues-via-commit-messages/).
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines.
The rest of the commit message is then used for this.
It's suggested to sign your commits. See: [How to sign commits](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits)
## Submit a pull request
Push your branch to your `alist` fork and open a pull request against the
`main` branch.
Please make sure your code has been formatted with `go fmt` or [prettier](https://prettier.io/) before submitting.
Push your branch to your `openlist` fork and open a pull request against the `main` branch.
## Merge your pull request
Your pull request will be merged after review. Please wait for the maintainer to merge your pull request after review.
At least 1 approving review is required by reviewers with write access. You can also request a review from maintainers.
## Delete your branch
(Optional) After your pull request is merged, you can delete your branch.
## AI Disclosure
If your pull request includes substantial AI-assisted content, disclose it in the PR description.
The pull request description must follow the repository's pull request template.
Fully automated contributions are not considered equivalent to normal community participation.
A contribution may be considered fully automated if it is submitted through an automated agent, or if the submitting account participates in project discussions through an automated agent, without meaningful human review or intervention.
When making this determination, maintainers may consider the overall behavior of the account, including but not limited to disclosed agent usage, interaction patterns, response characteristics, and other available evidence. No single factor is determinative.
Maintainers reserve the right to accept, reject, modify, or reimplement any contribution independently of any action taken against the submitting account. Acceptance of a contribution does not imply acceptance of the submitting account or its contribution method. If an account is determined to be primarily operated through automated processes, we may need to restrict its future participation in contributions until that determination is rescinded.
Please include:
- Tools used, such as ChatGPT, GitHub Copilot, Claude, Cursor, or other AI tools.
- Usage scope, such as code generation, refactoring, documentation, tests, translation, or review assistance.
- Confirmation that you have reviewed and validated all AI-assisted content before submission.
- Confirmation that the submitted content complies with this repository's license and contribution policies.
Minor AI assistance, such as typo fixes, autocomplete, formatting suggestions, or wording polish, does not need to be disclosed.
---
Thank you for your contribution! Let's make OpenList better together!
+23 -17
View File
@@ -1,30 +1,36 @@
FROM alpine:edge as builder
### Default image is base. You can add other support by modifying BASE_IMAGE_TAG. The following parameters are supported: base (default), aria2, ffmpeg, aio
ARG BASE_IMAGE_TAG=base
FROM alpine:edge AS builder
LABEL stage=go-builder
WORKDIR /app/
RUN apk add --no-cache bash curl gcc git go musl-dev
RUN apk add --no-cache bash curl jq gcc git go musl-dev
COPY go.mod go.sum ./
RUN go mod download
COPY ./ ./
RUN bash build.sh release docker
FROM alpine:edge
FROM openlistteam/openlist-base-image:${BASE_IMAGE_TAG}
LABEL MAINTAINER="OpenList"
ARG INSTALL_FFMPEG=false
LABEL MAINTAINER="i@nn.ci"
ARG INSTALL_ARIA2=false
ARG USER=openlist
ARG UID=1001
ARG GID=1001
WORKDIR /opt/alist/
WORKDIR /opt/openlist/
RUN apk update && \
apk upgrade --no-cache && \
apk add --no-cache bash ca-certificates su-exec tzdata; \
[ "$INSTALL_FFMPEG" = "true" ] && apk add --no-cache ffmpeg; \
rm -rf /var/cache/apk/*
RUN addgroup -g ${GID} ${USER} && \
adduser -D -u ${UID} -G ${USER} ${USER} && \
mkdir -p /opt/openlist/data
COPY --from=builder /app/bin/alist ./
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh && /entrypoint.sh version
COPY --from=builder --chmod=755 --chown=${UID}:${GID} /app/bin/openlist ./
COPY --chmod=755 --chown=${UID}:${GID} entrypoint.sh /entrypoint.sh
ENV PUID=0 PGID=0 UMASK=022
VOLUME /opt/alist/data/
USER ${USER}
RUN /entrypoint.sh version
ENV UMASK=022 RUN_ARIA2=${INSTALL_ARIA2}
VOLUME /opt/openlist/data/
EXPOSE 5244 5245
CMD [ "/entrypoint.sh" ]
CMD [ "/entrypoint.sh" ]
+18 -14
View File
@@ -1,22 +1,26 @@
FROM alpine:edge
ARG BASE_IMAGE_TAG=base
FROM ghcr.io/openlistteam/openlist-base-image:${BASE_IMAGE_TAG}
LABEL MAINTAINER="OpenList"
ARG TARGETPLATFORM
ARG INSTALL_FFMPEG=false
LABEL MAINTAINER="i@nn.ci"
ARG INSTALL_ARIA2=false
ARG USER=openlist
ARG UID=1001
ARG GID=1001
WORKDIR /opt/alist/
WORKDIR /opt/openlist/
RUN apk update && \
apk upgrade --no-cache && \
apk add --no-cache bash ca-certificates su-exec tzdata; \
[ "$INSTALL_FFMPEG" = "true" ] && apk add --no-cache ffmpeg; \
rm -rf /var/cache/apk/*
RUN addgroup -g ${GID} ${USER} && \
adduser -D -u ${UID} -G ${USER} ${USER} && \
mkdir -p /opt/openlist/data
COPY /build/${TARGETPLATFORM}/alist ./
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh && /entrypoint.sh version
COPY --chmod=755 --chown=${UID}:${GID} /build/${TARGETPLATFORM}/openlist ./
COPY --chmod=755 --chown=${UID}:${GID} entrypoint.sh /entrypoint.sh
ENV PUID=0 PGID=0 UMASK=022
VOLUME /opt/alist/data/
USER ${USER}
RUN /entrypoint.sh version
ENV UMASK=022 RUN_ARIA2=${INSTALL_ARIA2}
VOLUME /opt/openlist/data/
EXPOSE 5244 5245
CMD [ "/entrypoint.sh" ]
+128 -94
View File
@@ -1,82 +1,101 @@
<div align="center">
<a href="https://alist.nn.ci"><img width="100px" alt="logo" src="https://cdn.jsdelivr.net/gh/alist-org/logo@main/logo.svg"/></a>
<p><em>🗂️A file list program that supports multiple storages, powered by Gin and Solidjs.</em></p>
<div>
<a href="https://goreportcard.com/report/github.com/alist-org/alist/v3">
<img src="https://goreportcard.com/badge/github.com/alist-org/alist/v3" alt="latest version" />
</a>
<a href="https://github.com/alist-org/alist/blob/main/LICENSE">
<img src="https://img.shields.io/github/license/Xhofe/alist" alt="License" />
</a>
<a href="https://github.com/alist-org/alist/actions?query=workflow%3ABuild">
<img src="https://img.shields.io/github/actions/workflow/status/Xhofe/alist/build.yml?branch=main" alt="Build status" />
</a>
<a href="https://github.com/alist-org/alist/releases">
<img src="https://img.shields.io/github/release/Xhofe/alist" alt="latest version" />
</a>
<a title="Crowdin" target="_blank" href="https://crwd.in/alist">
<img src="https://badges.crowdin.net/alist/localized.svg">
</a>
</div>
<div>
<a href="https://github.com/alist-org/alist/discussions">
<img src="https://img.shields.io/github/discussions/Xhofe/alist?color=%23ED8936" alt="discussions" />
</a>
<a href="https://discord.gg/F4ymsH4xv2">
<img src="https://img.shields.io/discord/1018870125102895134?logo=discord" alt="discussions" />
</a>
<a href="https://github.com/alist-org/alist/releases">
<img src="https://img.shields.io/github/downloads/Xhofe/alist/total?color=%239F7AEA&logo=github" alt="Downloads" />
</a>
<a href="https://hub.docker.com/r/xhofe/alist">
<img src="https://img.shields.io/docker/pulls/xhofe/alist?color=%2348BB78&logo=docker&label=pulls" alt="Downloads" />
</a>
<a href="https://alist.nn.ci/guide/sponsor.html">
<img src="https://img.shields.io/badge/%24-sponsor-F87171.svg" alt="sponsor" />
</a>
</div>
<img src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg" width="128" height="128" alt="logo" />
<p><em>OpenList is a resilient, long-term governance, community-driven fork of AList — built to defend open source against trust-based attacks.</em></p>
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE"><img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" /></a>
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild"><img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" /></a>
<a href="https://github.com/OpenListTeam/OpenList/discussions"><img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" /></a>
</div>
---
English | [中文](./README_cn.md)| [日本語](./README_ja.md) | [Contributing](./CONTRIBUTING.md) | [CODE_OF_CONDUCT](./CODE_OF_CONDUCT.md)
- English | [中文](./README/README_cn.md) | [日本語](./README/README_ja.md) | [Dutch](./README/README_nl.md) | [한국어](./README/README_ko.md) | [Deutsch](./README/README_de.md) | [Русский](./README/README_ru.md) | [Français](./README/README_fr.md) | [Español](./README/README_es.md) | [العربية](./README/README_ar.md)
- [Contributing](./CONTRIBUTING.md)
- [CODE OF CONDUCT](./CODE_OF_CONDUCT.md)
- [LICENSE](./LICENSE)
## Disclaimer
OpenList is an open-source project independently maintained by the OpenList Team, following the AGPL-3.0 license and committed to maintaining complete code openness and modification transparency.
We have noticed the emergence of some third-party projects in the community with names similar to this project, such as OpenListApp/OpenListApp, as well as some paid proprietary software using the same or similar naming. To avoid user confusion, we hereby declare:
- OpenList has no official association with any third-party derivative projects.
- All software, code, and services of this project are maintained by the OpenList Team and are freely available on GitHub.
- Project documentation and API services primarily rely on charitable resources provided by Cloudflare. There are currently no paid plans or commercial deployments, and the use of existing features does not involve any costs.
We respect the community's rights to free use and derivative development, but we also strongly urge downstream projects:
- Should not use the "OpenList" name for impersonation promotion or commercial gain;
- Must not distribute OpenList-based code in a closed-source manner or violate AGPL license terms.
To better maintain healthy ecosystem development, we recommend:
- Clearly indicate the project source and choose appropriate open-source licenses in accordance with the open-source spirit;
- If involving commercial use, please avoid using "OpenList" or any confusing naming as the project name;
- If you need to use materials located under OpenListTeam/Logo, you may modify and use them under compliance with the agreement.
Thank you for your support and understanding of the OpenList project.
## Features
- [x] Multiple storages
- [x] Local storage
- [x] [Aliyundrive](https://www.alipan.com/)
- [x] OneDrive / Sharepoint ([global](https://www.office.com/), [cn](https://portal.partner.microsoftonline.cn),de,us)
- [x] [189cloud](https://cloud.189.cn) (Personal, Family)
- [x] [GoogleDrive](https://drive.google.com/)
- [x] [123pan](https://www.123pan.com/)
- [x] FTP / SFTP
- [x] [PikPak](https://www.mypikpak.com/)
- [x] [S3](https://aws.amazon.com/s3/)
- [x] [Seafile](https://seafile.com/)
- [x] [UPYUN Storage Service](https://www.upyun.com/products/file-storage)
- [x] WebDav(Support OneDrive/SharePoint without API)
- [x] Teambition([China](https://www.teambition.com/ ),[International](https://us.teambition.com/ ))
- [x] [Mediatrack](https://www.mediatrack.cn/)
- [x] [139yun](https://yun.139.com/) (Personal, Family)
- [x] [YandexDisk](https://disk.yandex.com/)
- [x] [BaiduNetdisk](http://pan.baidu.com/)
- [x] [Terabox](https://www.terabox.com/main)
- [x] [UC](https://drive.uc.cn)
- [x] [Quark](https://pan.quark.cn)
- [x] [Thunder](https://pan.xunlei.com)
- [x] [Lanzou](https://www.lanzou.com/)
- [x] [ILanzou](https://www.ilanzou.com/)
- [x] [Aliyundrive share](https://www.alipan.com/)
- [x] [Google photo](https://photos.google.com/)
- [x] [Mega.nz](https://mega.nz)
- [x] [Baidu photo](https://photo.baidu.com/)
- [x] SMB
- [x] [115](https://115.com/)
- [X] Cloudreve
- [x] [Dropbox](https://www.dropbox.com/)
- [x] [FeijiPan](https://www.feijipan.com/)
- [x] [dogecloud](https://www.dogecloud.com/product/oss)
- [x] Local storage
- [x] [Aliyundrive](https://www.alipan.com)
- [x] OneDrive / Sharepoint ([Global](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage), [CN](https://portal.partner.microsoftonline.cn), DE, US)
- [x] [189cloud](https://cloud.189.cn) (Personal, Family)
- [x] [GoogleDrive](https://drive.google.com)
- [x] [123pan](https://www.123pan.com)
- [x] [FTP / SFTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol)
- [x] [PikPak](https://www.mypikpak.com)
- [x] [S3](https://aws.amazon.com/s3)
- [x] [Seafile](https://seafile.com)
- [x] [UPYUN Storage Service](https://www.upyun.com/products/file-storage)
- [x] [WebDAV](https://en.wikipedia.org/wiki/WebDAV)
- [x] Teambition([China](https://www.teambition.com), [International](https://us.teambition.com))
- [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, Share)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
- [x] [UC](https://drive.uc.cn)
- [x] [Quark](https://pan.quark.cn)
- [x] [Thunder](https://pan.xunlei.com)
- [x] [Lanzou](https://www.lanzou.com)
- [x] [ILanzou](https://www.ilanzou.com)
- [x] [Google photo](https://photos.google.com)
- [x] [Mega.nz](https://mega.nz)
- [x] [Baidu photo](https://photo.baidu.com)
- [x] [SMB](https://en.wikipedia.org/wiki/Server_Message_Block)
- [x] [115](https://115.com)
- [X] [Cloudreve](https://cloudreve.org)
- [x] [Dropbox](https://www.dropbox.com)
- [x] [FeijiPan](https://www.feijipan.com)
- [x] [dogecloud](https://www.dogecloud.com/product/oss)
- [x] [Azure Blob Storage](https://azure.microsoft.com/products/storage/blobs)
- [x] [Chaoxing](https://www.chaoxing.com)
- [x] [CNB](https://cnb.cool/)
- [x] [Degoo](https://degoo.com)
- [x] [Doubao](https://www.doubao.com)
- [x] [Febbox](https://www.febbox.com)
- [x] [GitHub](https://github.com)
- [x] [OpenList](https://github.com/OpenListTeam/OpenList)
- [x] [Teldrive](https://github.com/tgdrive/teldrive)
- [x] [Weiyun](https://www.weiyun.com)
- [x] [DingTalk Docs](https://alidocs.dingtalk.com/)
- [x] Easy to deploy and out-of-the-box
- [x] File preview (PDF, markdown, code, plain text, ...)
- [x] Image preview in gallery mode
@@ -87,8 +106,8 @@ English | [中文](./README_cn.md)| [日本語](./README_ja.md) | [Contributing]
- [x] Dark mode
- [x] I18n
- [x] Protected routes (password protection and authentication)
- [x] WebDav (see https://alist.nn.ci/guide/webdav.html for details)
- [x] [Docker Deploy](https://hub.docker.com/r/xhofe/alist)
- [x] WebDAV
- [x] Docker Deploy
- [x] Cloudflare Workers proxy
- [x] File/Folder package download
- [x] Web upload(Can allow visitors to upload), delete, mkdir, rename, move and copy
@@ -98,44 +117,59 @@ English | [中文](./README_cn.md)| [日本語](./README_ja.md) | [Contributing]
## Document
<https://alist.nn.ci/>
- 📘 [Docs](https://doc.oplist.org)
- 🌏 [CN Mirror](https://doc.oplist.org.cn)
- ⚖️ [Terms of Use](https://doc.oplist.org/terms)
- 🔒 [Privacy Policy](https://doc.oplist.org/privacy)
## Demo
<https://al.nn.ci>
- 🌎 [Global Demo](https://demo.oplist.org)
- 🇨🇳 [CN Demo](https://demo.oplist.org.cn)
## Discussion
Please go to our [discussion forum](https://github.com/alist-org/alist/discussions) for general questions, **issues are for bug reports and feature requests only.**
Please refer to [*Discussions*](https://github.com/OpenListTeam/OpenList/discussions) for raising general questions, ***Issues* is for bug reports and feature requests only.**
## Sponsor
AList is an open-source software, if you happen to like this project and want me to keep going, please consider sponsoring me or providing a single donation! Thanks for all the love and support:
https://alist.nn.ci/guide/sponsor.html
[![VPS.Town](https://vps.town/static/images/sponsor.png)](https://vps.town "VPS.Town - Trust, Effortlessly. Your Cloud, Reimagined.")
### Special sponsors
## Donors
- [VidHub](https://apps.apple.com/app/apple-store/id1659622164?pt=118612019&ct=alist&mt=8) - An elegant cloud video player within the Apple ecosystem. Support for iPhone, iPad, Mac, and Apple TV.
- [亚洲云](https://www.asiayun.com/aff/QQCOOQKZ) - 高防服务器|服务器租用|福州高防|广东电信|香港服务器|美国服务器|海外服务器 - 国内靠谱的企业级云计算服务提供商 (sponsored Chinese API server)
- [找资源](http://zhaoziyuan2.cc/) - 阿里云盘资源搜索引擎
Thanks to the following donors for their generous support:
## Contributors
Thanks goes to these wonderful people:
[![Contributors](http://contrib.nn.ci/api?repo=alist-org/alist&repo=alist-org/alist-web&repo=alist-org/docs)](https://github.com/alist-org/alist/graphs/contributors)
- [HisAtri](https://github.com/HisAtri)
- 爱发电用户_7jTh
- suka
## License
The `AList` is open-source software licensed under the AGPL-3.0 license.
The `OpenList` is open-source software licensed under the [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) license.
## Disclaimer
- This program is a free and open source project. It is designed to share files on the network disk, which is convenient for downloading and learning Golang. Please abide by relevant laws and regulations when using it, and do not abuse it;
- This program is implemented by calling the official sdk/interface, without destroying the official interface behavior;
- This program only does 302 redirect/traffic forwarding, and does not intercept, store, or tamper with any user data;
- Before using this program, you should understand and bear the corresponding risks, including but not limited to account ban, download speed limit, etc., which is none of this program's business;
- If there is any infringement, please contact me by [email](mailto:i@nn.ci), and it will be dealt with in time.
---
- This project is a free and open-source software designed to facilitate file sharing via net disks, primarily intended to support the downloading and learning of the Go programming language.
- Please comply with all applicable laws and regulations when using this software. Any form of misuse is strictly prohibited.
- The software is based on official SDKs or APIs without any modification, disruption, or interference with their behavior.
- It only performs HTTP 302 redirects or traffic forwarding, and does not intercept, store, or tamper with any user data.
- This project is not affiliated with any official platform or service provider.
- The software is provided "as is", without any warranties of any kind, either express or implied, including but not limited to warranties of merchantability or fitness for a particular purpose.
- The maintainers are not liable for any direct or indirect damages arising from the use of, or inability to use, this software.
- You are solely responsible for any risks associated with using this software, including but not limited to account bans or download speed limitations.
- This project is licensed under the [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) License. Please see the [LICENSE](./LICENSE) file for details.
## Contact Us
- [@GitHub](https://github.com/OpenListTeam)
- [Telegram Group](https://t.me/OpenListTeam)
- [Telegram Channel](https://t.me/OpenListOfficial)
## Contributors
We sincerely thank the author [Xhofe](https://github.com/Xhofe) of the original project [AlistGo/alist](https://github.com/AlistGo/alist) and all other contributors.
Thanks goes to these wonderful people:
[![Contributors](https://contrib.rocks/image?repo=OpenListTeam/OpenList)](https://github.com/OpenListTeam/OpenList/graphs/contributors)
> [@Blog](https://nn.ci/) · [@GitHub](https://github.com/alist-org) · [@TelegramGroup](https://t.me/alist_chat) · [@Discord](https://discord.gg/F4ymsH4xv2)
+136
View File
@@ -0,0 +1,136 @@
<div align="center">
<img src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg" width="128" height="128" alt="logo" />
<p><em>OpenList هو تفرّع من AList يتميز بالمرونة والحوكمة طويلة الأمد ويقوده المجتمع، وقد بُني للدفاع عن البرمجيات مفتوحة المصدر ضد الهجمات القائمة على الثقة.</em></p>
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE"><img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" /></a>
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild"><img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" /></a>
<a href="https://github.com/OpenListTeam/OpenList/discussions"><img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" /></a>
</div>
---
- [English](../README.md) | [中文](./README_cn.md) | [日本語](./README_ja.md) | [Dutch](./README_nl.md) | [한국어](./README_ko.md) | [Deutsch](./README_de.md) | [Русский](./README_ru.md) | [Français](./README_fr.md) | [Español](./README_es.md) | العربية
- [Contributing](../CONTRIBUTING.md)
- [CODE OF CONDUCT](../CODE_OF_CONDUCT.md)
- [LICENSE](../LICENSE)
## إخلاء المسؤولية
OpenList is an open-source project independently maintained by the OpenList Team under the AGPL-3.0 license, with a commitment to code openness and modification transparency.
OpenList has no official association with third-party derivative projects that use similar names, including OpenListApp/OpenListApp or paid proprietary software using the same or similar names.
- All software, code, and services of this project are maintained by the OpenList Team and are freely available on GitHub.
- Project documentation and API services primarily rely on charitable resources provided by Cloudflare. There are currently no paid plans or commercial deployments.
- Downstream projects should not use the "OpenList" name for impersonation or commercial confusion, and must not distribute OpenList-based code as closed source in violation of the AGPL license.
- This software is provided "as is" without warranties. Please comply with applicable laws and regulations when using it.
## الميزات
- [x] Multiple storages
- [x] Local storage
- [x] [Aliyundrive](https://www.alipan.com)
- [x] OneDrive / Sharepoint ([Global](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage), [CN](https://portal.partner.microsoftonline.cn), DE, US)
- [x] [189cloud](https://cloud.189.cn) (Personal, Family)
- [x] [GoogleDrive](https://drive.google.com)
- [x] [123pan](https://www.123pan.com)
- [x] [FTP / SFTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol)
- [x] [PikPak](https://www.mypikpak.com)
- [x] [S3](https://aws.amazon.com/s3)
- [x] [Seafile](https://seafile.com)
- [x] [UPYUN Storage Service](https://www.upyun.com/products/file-storage)
- [x] [WebDAV](https://en.wikipedia.org/wiki/WebDAV)
- [x] Teambition([China](https://www.teambition.com), [International](https://us.teambition.com))
- [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, Share)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
- [x] [UC](https://drive.uc.cn)
- [x] [Quark](https://pan.quark.cn)
- [x] [Thunder](https://pan.xunlei.com)
- [x] [Lanzou](https://www.lanzou.com)
- [x] [ILanzou](https://www.ilanzou.com)
- [x] [Google photo](https://photos.google.com)
- [x] [Mega.nz](https://mega.nz)
- [x] [Baidu photo](https://photo.baidu.com)
- [x] [SMB](https://en.wikipedia.org/wiki/Server_Message_Block)
- [x] [115](https://115.com)
- [x] [Cloudreve](https://cloudreve.org)
- [x] [Dropbox](https://www.dropbox.com)
- [x] [FeijiPan](https://www.feijipan.com)
- [x] [dogecloud](https://www.dogecloud.com/product/oss)
- [x] [Azure Blob Storage](https://azure.microsoft.com/products/storage/blobs)
- [x] [Chaoxing](https://www.chaoxing.com)
- [x] [CNB](https://cnb.cool/)
- [x] [Degoo](https://degoo.com)
- [x] [Doubao](https://www.doubao.com)
- [x] [Febbox](https://www.febbox.com)
- [x] [GitHub](https://github.com)
- [x] [OpenList](https://github.com/OpenListTeam/OpenList)
- [x] [Teldrive](https://github.com/tgdrive/teldrive)
- [x] [Weiyun](https://www.weiyun.com)
- [x] [DingTalk Docs](https://alidocs.dingtalk.com/)
- [x] Easy to deploy and out-of-the-box
- [x] File preview (PDF, markdown, code, plain text, ...)
- [x] Image preview in gallery mode
- [x] Video and audio preview, with lyrics and subtitles support
- [x] Office document preview (docx, pptx, xlsx, ...)
- [x] `README.md` preview rendering
- [x] File permalink copy and direct file download
- [x] Dark mode and i18n
- [x] Protected routes, WebDAV, Docker deploy, and Cloudflare Workers proxy
- [x] File/folder package download and web upload operations
- [x] Offline download, cross-storage copy, and multi-thread download acceleration
## الوثائق
- 📘 [Docs](https://doc.oplist.org)
- 🌏 [CN Mirror](https://doc.oplist.org.cn)
- ⚖️ [Terms of Use](https://doc.oplist.org/terms)
- 🔒 [Privacy Policy](https://doc.oplist.org/privacy)
## العرض التجريبي
- 🌎 [Global Demo](https://demo.oplist.org)
- 🇨🇳 [CN Demo](https://demo.oplist.org.cn)
## النقاش
Please refer to [Discussions](https://github.com/OpenListTeam/OpenList/discussions) for general questions; Issues are for bug reports and feature requests only.
## الراعي
[![VPS.Town](https://vps.town/static/images/sponsor.png)](https://vps.town "VPS.Town - Trust, Effortlessly. Your Cloud, Reimagined.")
## المتبرعون
Thanks to the following donors for their generous support:
- [HisAtri](https://github.com/HisAtri)
- 爱发电用户_7jTh
- suka
## الترخيص
OpenList is open-source software licensed under the [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) license.
## تواصل معنا
- [@GitHub](https://github.com/OpenListTeam)
- [Telegram Group](https://t.me/OpenListTeam)
- [Telegram Channel](https://t.me/OpenListOfficial)
## المساهمون
We sincerely thank [Xhofe](https://github.com/Xhofe), author of the original project [AlistGo/alist](https://github.com/AlistGo/alist), and all other contributors.
[![Contributors](https://contrib.rocks/image?repo=OpenListTeam/OpenList)](https://github.com/OpenListTeam/OpenList/graphs/contributors)
+174
View File
@@ -0,0 +1,174 @@
<div align="center">
<img src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg" width="128" height="128" alt="logo" />
<p><em>OpenList 是一个有韧性、长期治理、社区驱动的 AList 分支,旨在防御基于信任的开源攻击。</em></p>
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE"><img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" /></a>
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild"><img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" /></a>
<a href="https://github.com/OpenListTeam/OpenList/discussions"><img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" /></a>
</div>
---
- [English](../README.md) | 中文 | [日本語](./README_ja.md) | [Dutch](./README_nl.md) | [한국어](./README_ko.md) | [Deutsch](./README_de.md) | [Русский](./README_ru.md) | [Français](./README_fr.md) | [Español](./README_es.md) | [العربية](./README_ar.md)
- [贡献指南](../CONTRIBUTING.md)
- [行为准则](../CODE_OF_CONDUCT.md)
- [许可证](../LICENSE)
## 免责声明
OpenList 是一个由 OpenList 团队独立维护的开源项目,遵循 AGPL-3.0 许可证,致力于保持完整的代码开放性和修改透明性。
我们注意到社区中出现了一些与本项目名称相似的第三方项目,如 OpenListApp/OpenListApp,以及部分采用相同或近似命名的收费专有软件。为避免用户误解,现声明如下:
- OpenList 与任何第三方衍生项目无官方关联。
- 本项目的全部软件、代码与服务由 OpenList 团队维护,可在 GitHub 免费获取。
- 项目文档与 API 服务均主要依托于 Cloudflare 提供的公益资源,目前无任何收费计划或商业部署,现有功能使用不涉及任何支出。
我们尊重社区的自由使用与衍生开发权利,但也强烈呼吁下游项目:
- 不应以“OpenList”名义进行冒名宣传或获取商业利益;
- 不得将基于 OpenList 的代码进行闭源分发或违反 AGPL 许可证条款。
为了更好地维护生态健康发展,我们建议:
- 明确注明项目来源,并以符合开源精神的方式选择适当的开源许可证;
- 如涉及商业用途,请避免使用“OpenList”或任何会产生混淆的方式作为项目名称;
- 若需使用本项目位于 OpenListTeam/Logo 下的素材,可在遵守协议的前提下进行修改后使用。
感谢您对 OpenList 项目的支持与理解。
## 功能
- [x] 多种存储
- [x] 本地存储
- [x] [阿里云盘](https://www.alipan.com)
- [x] OneDrive / Sharepoint ([国际版](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage), [中国](https://portal.partner.microsoftonline.cn), DE, US)
- [x] [天翼云盘](https://cloud.189.cn)(个人、家庭)
- [x] [GoogleDrive](https://drive.google.com)
- [x] [123云盘](https://www.123pan.com)
- [x] [FTP / SFTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol)
- [x] [PikPak](https://www.mypikpak.com)
- [x] [S3](https://aws.amazon.com/s3)
- [x] [Seafile](https://seafile.com)
- [x] [又拍云对象存储](https://www.upyun.com/products/file-storage)
- [x] [WebDAV](https://en.wikipedia.org/wiki/WebDAV)
- [x] Teambition([中国](https://www.teambition.com), [国际](https://us.teambition.com))
- [x] [MediaFire](https://www.mediafire.com)
- [x] [分秒帧](https://www.mediatrack.cn)
- [x] [ProtonDrive](https://proton.me/drive)
- [x] [和彩云](https://yun.139.com)(个人、家庭、群组、分享)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [百度网盘](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
- [x] [UC网盘](https://drive.uc.cn)
- [x] [夸克网盘](https://pan.quark.cn)
- [x] [迅雷网盘](https://pan.xunlei.com)
- [x] [蓝奏云](https://www.lanzou.com)
- [x] [蓝奏云优享版](https://www.ilanzou.com)
- [x] [Google 相册](https://photos.google.com)
- [x] [Mega.nz](https://mega.nz)
- [x] [百度相册](https://photo.baidu.com)
- [x] [SMB](https://en.wikipedia.org/wiki/Server_Message_Block)
- [x] [115](https://115.com)
- [x] [Cloudreve](https://cloudreve.org)
- [x] [Dropbox](https://www.dropbox.com)
- [x] [飞机盘](https://www.feijipan.com)
- [x] [多吉云](https://www.dogecloud.com/product/oss)
- [x] [Azure Blob Storage](https://azure.microsoft.com/products/storage/blobs)
- [x] [超星](https://www.chaoxing.com)
- [x] [CNB](https://cnb.cool/)
- [x] [Degoo](https://degoo.com)
- [x] [豆包](https://www.doubao.com)
- [x] [Febbox](https://www.febbox.com)
- [x] [GitHub](https://github.com)
- [x] [OpenList](https://github.com/OpenListTeam/OpenList)
- [x] [Teldrive](https://github.com/tgdrive/teldrive)
- [x] [微云](https://www.weiyun.com)
- [x] [钉钉文档](https://alidocs.dingtalk.com/)
- [x] 部署方便,开箱即用
- [x] 文件预览(PDF、markdown、代码、纯文本等)
- [x] 画廊模式下的图片预览
- [x] 视频和音频预览,支持歌词和字幕
- [x] Office 文档预览(docx、pptx、xlsx 等)
- [x] `README.md` 预览渲染
- [x] 文件永久链接复制和直接文件下载
- [x] 黑暗模式
- [x] 国际化
- [x] 受保护的路由(密码保护和认证)
- [x] WebDAV
- [x] Docker 部署
- [x] Cloudflare Workers 代理
- [x] 文件/文件夹打包下载
- [x] 网页上传(可允许访客上传)、删除、新建文件夹、重命名、移动和复制
- [x] 离线下载
- [x] 跨存储复制文件
- [x] 单文件多线程下载/流式加速
## 文档
- 📘 [文档](https://doc.oplist.org)
- 🌏 [中国镜像](https://doc.oplist.org.cn)
- ⚖️ [使用条款](https://doc.oplist.org/terms)
- 🔒 [隐私政策](https://doc.oplist.org/privacy)
## Demo
- 🌎 [全球 Demo](https://demo.oplist.org)
- 🇨🇳 [中国 Demo](https://demo.oplist.org.cn)
## 讨论
如有一般性问题请前往 [*Discussions*](https://github.com/OpenListTeam/OpenList/discussions) 讨论区,***Issues* 仅用于错误报告和功能请求。**
## 赞助者
[![VPS.Town](https://vps.town/static/images/sponsor.png)](https://vps.town "VPS.Town - Trust, Effortlessly. Your Cloud, Reimagined.")
## 捐赠者
感谢以下捐赠者的慷慨支持:
- [HisAtri](https://github.com/HisAtri)
- 爱发电用户_7jTh
- suka
## 许可证
`OpenList` 是基于 [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) 许可证的开源软件。
## 免责声明
- 本项目为免费开源软件,旨在通过网盘便捷分享文件,主要用于 Go 语言的下载与学习。
- 使用本软件时请遵守相关法律法规,严禁任何形式的滥用。
- 本软件基于官方 SDK 或 API 实现,未对其行为进行任何修改、破坏或干扰。
- 仅进行 HTTP 302 跳转或流量转发,不拦截、存储或篡改任何用户数据。
- 本项目与任何官方平台或服务提供商无关。
- 本软件按“原样”提供,不附带任何明示或暗示的担保,包括但不限于适销性或特定用途的适用性。
- 维护者不对因使用或无法使用本软件而导致的任何直接或间接损失负责。
- 您需自行承担使用本软件的所有风险,包括但不限于账号被封、下载限速等。
- 本项目遵循 [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) 许可证,详情请参见 [LICENSE](../LICENSE) 文件。
## 联系我们
- [@GitHub](https://github.com/OpenListTeam)
- [Telegram 交流群](https://t.me/OpenListTeam)
- [Telegram 频道](https://t.me/OpenListOfficial)
## 贡献者
我们衷心感谢原项目 [AlistGo/alist](https://github.com/AlistGo/alist) 的作者 [Xhofe](https://github.com/Xhofe) 及所有其他贡献者。
感谢这些优秀的人:
[![Contributors](https://contrib.rocks/image?repo=OpenListTeam/OpenList)](https://github.com/OpenListTeam/OpenList/graphs/contributors)
+136
View File
@@ -0,0 +1,136 @@
<div align="center">
<img src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg" width="128" height="128" alt="logo" />
<p><em>OpenList ist ein widerstandsfähiger, langfristig verwalteter und Community-getriebener Fork von AList, entwickelt zum Schutz von Open Source vor vertrauensbasierten Angriffen.</em></p>
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE"><img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" /></a>
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild"><img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" /></a>
<a href="https://github.com/OpenListTeam/OpenList/discussions"><img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" /></a>
</div>
---
- [English](../README.md) | [中文](./README_cn.md) | [日本語](./README_ja.md) | [Dutch](./README_nl.md) | [한국어](./README_ko.md) | Deutsch | [Русский](./README_ru.md) | [Français](./README_fr.md) | [Español](./README_es.md) | [العربية](./README_ar.md)
- [Contributing](../CONTRIBUTING.md)
- [CODE OF CONDUCT](../CODE_OF_CONDUCT.md)
- [LICENSE](../LICENSE)
## Haftungsausschluss
OpenList is an open-source project independently maintained by the OpenList Team under the AGPL-3.0 license, with a commitment to code openness and modification transparency.
OpenList has no official association with third-party derivative projects that use similar names, including OpenListApp/OpenListApp or paid proprietary software using the same or similar names.
- All software, code, and services of this project are maintained by the OpenList Team and are freely available on GitHub.
- Project documentation and API services primarily rely on charitable resources provided by Cloudflare. There are currently no paid plans or commercial deployments.
- Downstream projects should not use the "OpenList" name for impersonation or commercial confusion, and must not distribute OpenList-based code as closed source in violation of the AGPL license.
- This software is provided "as is" without warranties. Please comply with applicable laws and regulations when using it.
## Funktionen
- [x] Multiple storages
- [x] Local storage
- [x] [Aliyundrive](https://www.alipan.com)
- [x] OneDrive / Sharepoint ([Global](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage), [CN](https://portal.partner.microsoftonline.cn), DE, US)
- [x] [189cloud](https://cloud.189.cn) (Personal, Family)
- [x] [GoogleDrive](https://drive.google.com)
- [x] [123pan](https://www.123pan.com)
- [x] [FTP / SFTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol)
- [x] [PikPak](https://www.mypikpak.com)
- [x] [S3](https://aws.amazon.com/s3)
- [x] [Seafile](https://seafile.com)
- [x] [UPYUN Storage Service](https://www.upyun.com/products/file-storage)
- [x] [WebDAV](https://en.wikipedia.org/wiki/WebDAV)
- [x] Teambition([China](https://www.teambition.com), [International](https://us.teambition.com))
- [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, Share)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
- [x] [UC](https://drive.uc.cn)
- [x] [Quark](https://pan.quark.cn)
- [x] [Thunder](https://pan.xunlei.com)
- [x] [Lanzou](https://www.lanzou.com)
- [x] [ILanzou](https://www.ilanzou.com)
- [x] [Google photo](https://photos.google.com)
- [x] [Mega.nz](https://mega.nz)
- [x] [Baidu photo](https://photo.baidu.com)
- [x] [SMB](https://en.wikipedia.org/wiki/Server_Message_Block)
- [x] [115](https://115.com)
- [x] [Cloudreve](https://cloudreve.org)
- [x] [Dropbox](https://www.dropbox.com)
- [x] [FeijiPan](https://www.feijipan.com)
- [x] [dogecloud](https://www.dogecloud.com/product/oss)
- [x] [Azure Blob Storage](https://azure.microsoft.com/products/storage/blobs)
- [x] [Chaoxing](https://www.chaoxing.com)
- [x] [CNB](https://cnb.cool/)
- [x] [Degoo](https://degoo.com)
- [x] [Doubao](https://www.doubao.com)
- [x] [Febbox](https://www.febbox.com)
- [x] [GitHub](https://github.com)
- [x] [OpenList](https://github.com/OpenListTeam/OpenList)
- [x] [Teldrive](https://github.com/tgdrive/teldrive)
- [x] [Weiyun](https://www.weiyun.com)
- [x] [DingTalk Docs](https://alidocs.dingtalk.com/)
- [x] Easy to deploy and out-of-the-box
- [x] File preview (PDF, markdown, code, plain text, ...)
- [x] Image preview in gallery mode
- [x] Video and audio preview, with lyrics and subtitles support
- [x] Office document preview (docx, pptx, xlsx, ...)
- [x] `README.md` preview rendering
- [x] File permalink copy and direct file download
- [x] Dark mode and i18n
- [x] Protected routes, WebDAV, Docker deploy, and Cloudflare Workers proxy
- [x] File/folder package download and web upload operations
- [x] Offline download, cross-storage copy, and multi-thread download acceleration
## Dokumentation
- 📘 [Docs](https://doc.oplist.org)
- 🌏 [CN Mirror](https://doc.oplist.org.cn)
- ⚖️ [Terms of Use](https://doc.oplist.org/terms)
- 🔒 [Privacy Policy](https://doc.oplist.org/privacy)
## Demo
- 🌎 [Global Demo](https://demo.oplist.org)
- 🇨🇳 [CN Demo](https://demo.oplist.org.cn)
## Diskussion
Please refer to [Discussions](https://github.com/OpenListTeam/OpenList/discussions) for general questions; Issues are for bug reports and feature requests only.
## Sponsor
[![VPS.Town](https://vps.town/static/images/sponsor.png)](https://vps.town "VPS.Town - Trust, Effortlessly. Your Cloud, Reimagined.")
## Spender
Thanks to the following donors for their generous support:
- [HisAtri](https://github.com/HisAtri)
- 爱发电用户_7jTh
- suka
## Lizenz
OpenList is open-source software licensed under the [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) license.
## Kontakt
- [@GitHub](https://github.com/OpenListTeam)
- [Telegram Group](https://t.me/OpenListTeam)
- [Telegram Channel](https://t.me/OpenListOfficial)
## Mitwirkende
We sincerely thank [Xhofe](https://github.com/Xhofe), author of the original project [AlistGo/alist](https://github.com/AlistGo/alist), and all other contributors.
[![Contributors](https://contrib.rocks/image?repo=OpenListTeam/OpenList)](https://github.com/OpenListTeam/OpenList/graphs/contributors)
+136
View File
@@ -0,0 +1,136 @@
<div align="center">
<img src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg" width="128" height="128" alt="logo" />
<p><em>OpenList es un fork de AList resiliente, con gobernanza a largo plazo e impulsado por la comunidad, creado para defender el código abierto frente a ataques basados en la confianza.</em></p>
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE"><img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" /></a>
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild"><img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" /></a>
<a href="https://github.com/OpenListTeam/OpenList/discussions"><img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" /></a>
</div>
---
- [English](../README.md) | [中文](./README_cn.md) | [日本語](./README_ja.md) | [Dutch](./README_nl.md) | [한국어](./README_ko.md) | [Deutsch](./README_de.md) | [Русский](./README_ru.md) | [Français](./README_fr.md) | Español | [العربية](./README_ar.md)
- [Contributing](../CONTRIBUTING.md)
- [CODE OF CONDUCT](../CODE_OF_CONDUCT.md)
- [LICENSE](../LICENSE)
## Aviso legal
OpenList is an open-source project independently maintained by the OpenList Team under the AGPL-3.0 license, with a commitment to code openness and modification transparency.
OpenList has no official association with third-party derivative projects that use similar names, including OpenListApp/OpenListApp or paid proprietary software using the same or similar names.
- All software, code, and services of this project are maintained by the OpenList Team and are freely available on GitHub.
- Project documentation and API services primarily rely on charitable resources provided by Cloudflare. There are currently no paid plans or commercial deployments.
- Downstream projects should not use the "OpenList" name for impersonation or commercial confusion, and must not distribute OpenList-based code as closed source in violation of the AGPL license.
- This software is provided "as is" without warranties. Please comply with applicable laws and regulations when using it.
## Características
- [x] Multiple storages
- [x] Local storage
- [x] [Aliyundrive](https://www.alipan.com)
- [x] OneDrive / Sharepoint ([Global](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage), [CN](https://portal.partner.microsoftonline.cn), DE, US)
- [x] [189cloud](https://cloud.189.cn) (Personal, Family)
- [x] [GoogleDrive](https://drive.google.com)
- [x] [123pan](https://www.123pan.com)
- [x] [FTP / SFTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol)
- [x] [PikPak](https://www.mypikpak.com)
- [x] [S3](https://aws.amazon.com/s3)
- [x] [Seafile](https://seafile.com)
- [x] [UPYUN Storage Service](https://www.upyun.com/products/file-storage)
- [x] [WebDAV](https://en.wikipedia.org/wiki/WebDAV)
- [x] Teambition([China](https://www.teambition.com), [International](https://us.teambition.com))
- [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, Share)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
- [x] [UC](https://drive.uc.cn)
- [x] [Quark](https://pan.quark.cn)
- [x] [Thunder](https://pan.xunlei.com)
- [x] [Lanzou](https://www.lanzou.com)
- [x] [ILanzou](https://www.ilanzou.com)
- [x] [Google photo](https://photos.google.com)
- [x] [Mega.nz](https://mega.nz)
- [x] [Baidu photo](https://photo.baidu.com)
- [x] [SMB](https://en.wikipedia.org/wiki/Server_Message_Block)
- [x] [115](https://115.com)
- [x] [Cloudreve](https://cloudreve.org)
- [x] [Dropbox](https://www.dropbox.com)
- [x] [FeijiPan](https://www.feijipan.com)
- [x] [dogecloud](https://www.dogecloud.com/product/oss)
- [x] [Azure Blob Storage](https://azure.microsoft.com/products/storage/blobs)
- [x] [Chaoxing](https://www.chaoxing.com)
- [x] [CNB](https://cnb.cool/)
- [x] [Degoo](https://degoo.com)
- [x] [Doubao](https://www.doubao.com)
- [x] [Febbox](https://www.febbox.com)
- [x] [GitHub](https://github.com)
- [x] [OpenList](https://github.com/OpenListTeam/OpenList)
- [x] [Teldrive](https://github.com/tgdrive/teldrive)
- [x] [Weiyun](https://www.weiyun.com)
- [x] [DingTalk Docs](https://alidocs.dingtalk.com/)
- [x] Easy to deploy and out-of-the-box
- [x] File preview (PDF, markdown, code, plain text, ...)
- [x] Image preview in gallery mode
- [x] Video and audio preview, with lyrics and subtitles support
- [x] Office document preview (docx, pptx, xlsx, ...)
- [x] `README.md` preview rendering
- [x] File permalink copy and direct file download
- [x] Dark mode and i18n
- [x] Protected routes, WebDAV, Docker deploy, and Cloudflare Workers proxy
- [x] File/folder package download and web upload operations
- [x] Offline download, cross-storage copy, and multi-thread download acceleration
## Documentación
- 📘 [Docs](https://doc.oplist.org)
- 🌏 [CN Mirror](https://doc.oplist.org.cn)
- ⚖️ [Terms of Use](https://doc.oplist.org/terms)
- 🔒 [Privacy Policy](https://doc.oplist.org/privacy)
## Demo
- 🌎 [Global Demo](https://demo.oplist.org)
- 🇨🇳 [CN Demo](https://demo.oplist.org.cn)
## Discusión
Please refer to [Discussions](https://github.com/OpenListTeam/OpenList/discussions) for general questions; Issues are for bug reports and feature requests only.
## Patrocinador
[![VPS.Town](https://vps.town/static/images/sponsor.png)](https://vps.town "VPS.Town - Trust, Effortlessly. Your Cloud, Reimagined.")
## Donantes
Thanks to the following donors for their generous support:
- [HisAtri](https://github.com/HisAtri)
- 爱发电用户_7jTh
- suka
## Licencia
OpenList is open-source software licensed under the [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) license.
## Contacto
- [@GitHub](https://github.com/OpenListTeam)
- [Telegram Group](https://t.me/OpenListTeam)
- [Telegram Channel](https://t.me/OpenListOfficial)
## Colaboradores
We sincerely thank [Xhofe](https://github.com/Xhofe), author of the original project [AlistGo/alist](https://github.com/AlistGo/alist), and all other contributors.
[![Contributors](https://contrib.rocks/image?repo=OpenListTeam/OpenList)](https://github.com/OpenListTeam/OpenList/graphs/contributors)
+136
View File
@@ -0,0 +1,136 @@
<div align="center">
<img src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg" width="128" height="128" alt="logo" />
<p><em>OpenList est un fork d’AList résilient, gouverné sur le long terme et porté par la communauté, conçu pour protéger l’open source contre les attaques fondées sur la confiance.</em></p>
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE"><img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" /></a>
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild"><img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" /></a>
<a href="https://github.com/OpenListTeam/OpenList/discussions"><img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" /></a>
</div>
---
- [English](../README.md) | [中文](./README_cn.md) | [日本語](./README_ja.md) | [Dutch](./README_nl.md) | [한국어](./README_ko.md) | [Deutsch](./README_de.md) | [Русский](./README_ru.md) | Français | [Español](./README_es.md) | [العربية](./README_ar.md)
- [Contributing](../CONTRIBUTING.md)
- [CODE OF CONDUCT](../CODE_OF_CONDUCT.md)
- [LICENSE](../LICENSE)
## Avertissement
OpenList is an open-source project independently maintained by the OpenList Team under the AGPL-3.0 license, with a commitment to code openness and modification transparency.
OpenList has no official association with third-party derivative projects that use similar names, including OpenListApp/OpenListApp or paid proprietary software using the same or similar names.
- All software, code, and services of this project are maintained by the OpenList Team and are freely available on GitHub.
- Project documentation and API services primarily rely on charitable resources provided by Cloudflare. There are currently no paid plans or commercial deployments.
- Downstream projects should not use the "OpenList" name for impersonation or commercial confusion, and must not distribute OpenList-based code as closed source in violation of the AGPL license.
- This software is provided "as is" without warranties. Please comply with applicable laws and regulations when using it.
## Fonctionnalités
- [x] Multiple storages
- [x] Local storage
- [x] [Aliyundrive](https://www.alipan.com)
- [x] OneDrive / Sharepoint ([Global](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage), [CN](https://portal.partner.microsoftonline.cn), DE, US)
- [x] [189cloud](https://cloud.189.cn) (Personal, Family)
- [x] [GoogleDrive](https://drive.google.com)
- [x] [123pan](https://www.123pan.com)
- [x] [FTP / SFTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol)
- [x] [PikPak](https://www.mypikpak.com)
- [x] [S3](https://aws.amazon.com/s3)
- [x] [Seafile](https://seafile.com)
- [x] [UPYUN Storage Service](https://www.upyun.com/products/file-storage)
- [x] [WebDAV](https://en.wikipedia.org/wiki/WebDAV)
- [x] Teambition([China](https://www.teambition.com), [International](https://us.teambition.com))
- [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, Share)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
- [x] [UC](https://drive.uc.cn)
- [x] [Quark](https://pan.quark.cn)
- [x] [Thunder](https://pan.xunlei.com)
- [x] [Lanzou](https://www.lanzou.com)
- [x] [ILanzou](https://www.ilanzou.com)
- [x] [Google photo](https://photos.google.com)
- [x] [Mega.nz](https://mega.nz)
- [x] [Baidu photo](https://photo.baidu.com)
- [x] [SMB](https://en.wikipedia.org/wiki/Server_Message_Block)
- [x] [115](https://115.com)
- [x] [Cloudreve](https://cloudreve.org)
- [x] [Dropbox](https://www.dropbox.com)
- [x] [FeijiPan](https://www.feijipan.com)
- [x] [dogecloud](https://www.dogecloud.com/product/oss)
- [x] [Azure Blob Storage](https://azure.microsoft.com/products/storage/blobs)
- [x] [Chaoxing](https://www.chaoxing.com)
- [x] [CNB](https://cnb.cool/)
- [x] [Degoo](https://degoo.com)
- [x] [Doubao](https://www.doubao.com)
- [x] [Febbox](https://www.febbox.com)
- [x] [GitHub](https://github.com)
- [x] [OpenList](https://github.com/OpenListTeam/OpenList)
- [x] [Teldrive](https://github.com/tgdrive/teldrive)
- [x] [Weiyun](https://www.weiyun.com)
- [x] [DingTalk Docs](https://alidocs.dingtalk.com/)
- [x] Easy to deploy and out-of-the-box
- [x] File preview (PDF, markdown, code, plain text, ...)
- [x] Image preview in gallery mode
- [x] Video and audio preview, with lyrics and subtitles support
- [x] Office document preview (docx, pptx, xlsx, ...)
- [x] `README.md` preview rendering
- [x] File permalink copy and direct file download
- [x] Dark mode and i18n
- [x] Protected routes, WebDAV, Docker deploy, and Cloudflare Workers proxy
- [x] File/folder package download and web upload operations
- [x] Offline download, cross-storage copy, and multi-thread download acceleration
## Documentation
- 📘 [Docs](https://doc.oplist.org)
- 🌏 [CN Mirror](https://doc.oplist.org.cn)
- ⚖️ [Terms of Use](https://doc.oplist.org/terms)
- 🔒 [Privacy Policy](https://doc.oplist.org/privacy)
## Démo
- 🌎 [Global Demo](https://demo.oplist.org)
- 🇨🇳 [CN Demo](https://demo.oplist.org.cn)
## Discussion
Please refer to [Discussions](https://github.com/OpenListTeam/OpenList/discussions) for general questions; Issues are for bug reports and feature requests only.
## Sponsor
[![VPS.Town](https://vps.town/static/images/sponsor.png)](https://vps.town "VPS.Town - Trust, Effortlessly. Your Cloud, Reimagined.")
## Donateurs
Thanks to the following donors for their generous support:
- [HisAtri](https://github.com/HisAtri)
- 爱发电用户_7jTh
- suka
## Licence
OpenList is open-source software licensed under the [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) license.
## Nous contacter
- [@GitHub](https://github.com/OpenListTeam)
- [Telegram Group](https://t.me/OpenListTeam)
- [Telegram Channel](https://t.me/OpenListOfficial)
## Contributeurs
We sincerely thank [Xhofe](https://github.com/Xhofe), author of the original project [AlistGo/alist](https://github.com/AlistGo/alist), and all other contributors.
[![Contributors](https://contrib.rocks/image?repo=OpenListTeam/OpenList)](https://github.com/OpenListTeam/OpenList/graphs/contributors)
+174
View File
@@ -0,0 +1,174 @@
<div align="center">
<img src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg" width="128" height="128" alt="logo" />
<p><em>OpenList は、信頼ベースの攻撃からオープンソースを守るために構築された、レジリエントで長期ガバナンス、コミュニティ主導の AList フォークです。</em></p>
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE"><img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" /></a>
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild"><img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" /></a>
<a href="https://github.com/OpenListTeam/OpenList/discussions"><img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" /></a>
</div>
---
- [English](../README.md) | [中文](./README_cn.md) | 日本語 | [Dutch](./README_nl.md) | [한국어](./README_ko.md) | [Deutsch](./README_de.md) | [Русский](./README_ru.md) | [Français](./README_fr.md) | [Español](./README_es.md) | [العربية](./README_ar.md)
- [コントリビュート](../CONTRIBUTING.md)
- [行動規範](../CODE_OF_CONDUCT.md)
- [ライセンス](../LICENSE)
## 免責事項
OpenListは、OpenListチームが独立して維持するオープンソースプロジェクトであり、AGPL-3.0ライセンスに従い、完全なコードの開放性と変更の透明性を維持することに専念しています。
コミュニティ内で、OpenListApp/OpenListAppなど、本プロジェクトと類似した名称を持つサードパーティプロジェクトや、同一または類似した命名を採用する有料専有ソフトウェアが出現していることを確認しています。ユーザーの誤解を避けるため、以下のように宣言いたします:
- OpenListは、いかなるサードパーティ派生プロジェクトとも公式な関連性はありません。
- 本プロジェクトのすべてのソフトウェア、コード、サービスはOpenListチームによって維持され、GitHubで無料で取得できます。
- プロジェクトドキュメントとAPIサービスは主にCloudflareが提供する公益リソースに依存しており、現在有料プランや商業展開はなく、既存機能の使用に費用は発生しません。
私たちはコミュニティの自由な使用と派生開発の権利を尊重しますが、下流プロジェクトに強く呼びかけます:
- 「OpenList」の名前で偽装宣伝や商業利益を得るべきではありません;
- OpenListベースのコードをクローズドソースで配布したり、AGPLライセンス条項に違反してはいけません。
エコシステムの健全な発展をより良く維持するため、以下を推奨します:
- プロジェクトの出典を明確に示し、オープンソース精神に合致する適切なオープンソースライセンスを選択する;
- 商業用途が関わる場合は、「OpenList」や混乱を招く可能性のある名前をプロジェクト名として使用することを避ける;
- OpenListTeam/Logo下の素材を使用する必要がある場合は、協定を遵守した上で修正して使用できます。
OpenListプロジェクトへのご支援とご理解をありがとうございます。
## 特徴
- [x] 複数ストレージ
- [x] ローカルストレージ
- [x] [Aliyundrive](https://www.alipan.com)
- [x] OneDrive / Sharepoint ([グローバル](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage), [中国](https://portal.partner.microsoftonline.cn), DE, US)
- [x] [189cloud](https://cloud.189.cn)(個人、家族)
- [x] [GoogleDrive](https://drive.google.com)
- [x] [123pan](https://www.123pan.com)
- [x] [FTP / SFTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol)
- [x] [PikPak](https://www.mypikpak.com)
- [x] [S3](https://aws.amazon.com/s3)
- [x] [Seafile](https://seafile.com)
- [x] [UPYUN Storage Service](https://www.upyun.com/products/file-storage)
- [x] [WebDAV](https://en.wikipedia.org/wiki/WebDAV)
- [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] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
- [x] [UC](https://drive.uc.cn)
- [x] [Quark](https://pan.quark.cn)
- [x] [Thunder](https://pan.xunlei.com)
- [x] [Lanzou](https://www.lanzou.com)
- [x] [ILanzou](https://www.ilanzou.com)
- [x] [Google photo](https://photos.google.com)
- [x] [Mega.nz](https://mega.nz)
- [x] [Baidu photo](https://photo.baidu.com)
- [x] [SMB](https://en.wikipedia.org/wiki/Server_Message_Block)
- [x] [115](https://115.com)
- [x] [Cloudreve](https://cloudreve.org)
- [x] [Dropbox](https://www.dropbox.com)
- [x] [FeijiPan](https://www.feijipan.com)
- [x] [dogecloud](https://www.dogecloud.com/product/oss)
- [x] [Azure Blob Storage](https://azure.microsoft.com/products/storage/blobs)
- [x] [Chaoxing](https://www.chaoxing.com)
- [x] [CNB](https://cnb.cool/)
- [x] [Degoo](https://degoo.com)
- [x] [Doubao](https://www.doubao.com)
- [x] [Febbox](https://www.febbox.com)
- [x] [GitHub](https://github.com)
- [x] [OpenList](https://github.com/OpenListTeam/OpenList)
- [x] [Teldrive](https://github.com/tgdrive/teldrive)
- [x] [Weiyun](https://www.weiyun.com)
- [x] [DingTalk ドキュメント](https://alidocs.dingtalk.com/)
- [x] [MediaFire](https://www.mediafire.com)
- [x] 簡単にデプロイでき、すぐに使える
- [x] ファイルプレビュー(PDF、markdown、コード、テキストなど)
- [x] ギャラリーモードでの画像プレビュー
- [x] ビデオ・オーディオプレビュー、歌詞・字幕対応
- [x] Officeドキュメントプレビュー(docx、pptx、xlsxなど)
- [x] `README.md` プレビュー表示
- [x] ファイルのパーマリンクコピーと直接ダウンロード
- [x] ダークモード
- [x] 国際化対応
- [x] 保護されたルート(パスワード保護と認証)
- [x] WebDAV
- [x] Dockerデプロイ
- [x] Cloudflare Workersプロキシ
- [x] ファイル/フォルダのパッケージダウンロード
- [x] Webアップロード(訪問者のアップロード許可可)、削除、フォルダ作成、リネーム、移動、コピー
- [x] オフラインダウンロード
- [x] ストレージ間のファイルコピー
- [x] 単一ファイルのマルチスレッドダウンロード/ストリーム加速
## ドキュメント
- 📘 [ドキュメント](https://doc.oplist.org)
- 🌏 [中国ミラー](https://doc.oplist.org.cn)
- ⚖️ [利用規約](https://doc.oplist.org/terms)
- 🔒 [プライバシーポリシー](https://doc.oplist.org/privacy)
## Demo
- 🌎 [グローバル Demo](https://demo.oplist.org)
- 🇨🇳 [中国 Demo](https://demo.oplist.org.cn)
## ディスカッション
一般的な質問は [*Discussions*](https://github.com/OpenListTeam/OpenList/discussions) をご利用ください。***Issues* はバグ報告と機能リクエスト専用です。**
## スポンサー
[![VPS.Town](https://vps.town/static/images/sponsor.png)](https://vps.town "VPS.Town - Trust, Effortlessly. Your Cloud, Reimagined.")
## 寄付者
以下の方々の寛大なご支援に感謝いたします:
- [HisAtri](https://github.com/HisAtri)
- 爱发电用户_7jTh
- suka
## ライセンス
「OpenList」は [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) ライセンスの下で公開されているオープンソースソフトウェアです。
## 免責事項
- 本プロジェクトは無料のオープンソースソフトウェアであり、ネットワークディスクを通じたファイル共有を容易にすることを目的とし、主に Go 言語のダウンロードと学習をサポートします。
- 本ソフトウェアの利用にあたっては、関連する法令を遵守し、不正利用を固く禁じます。
- 本ソフトウェアは公式 SDK または API に基づいており、その動作を一切改変・破壊・妨害しません。
- 302 リダイレクトまたはトラフィック転送のみを行い、ユーザーデータの傍受・保存・改ざんは一切行いません。
- 本プロジェクトは、いかなる公式プラットフォームやサービスプロバイダーとも関係ありません。
- 本ソフトウェアは「現状有姿」で提供されており、商品性や特定目的への適合性を含むいかなる保証もありません。
- 本ソフトウェアの使用または使用不能によるいかなる直接的・間接的損害についても、メンテナは責任を負いません。
- 本ソフトウェアの利用に伴うすべてのリスク(アカウントの凍結やダウンロード速度制限などを含む)は、利用者自身が負うものとします。
- 本プロジェクトは [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) ライセンスに従います。詳細は [LICENSE](../LICENSE) ファイルをご覧ください。
## お問い合わせ
- [@GitHub](https://github.com/OpenListTeam)
- [Telegram グループ](https://t.me/OpenListTeam)
- [Telegram チャンネル](https://t.me/OpenListOfficial)
## コントリビューター
オリジナルプロジェクト [AlistGo/alist](https://github.com/AlistGo/alist) の作者 [Xhofe](https://github.com/Xhofe) およびその他すべての貢献者に心より感謝いたします。
素晴らしい皆様に感謝します:
[![Contributors](https://contrib.rocks/image?repo=OpenListTeam/OpenList)](https://github.com/OpenListTeam/OpenList/graphs/contributors)
+136
View File
@@ -0,0 +1,136 @@
<div align="center">
<img src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg" width="128" height="128" alt="logo" />
<p><em>OpenList는 신뢰 기반 공격으로부터 오픈 소스를 보호하기 위해 만들어진, 탄력적이고 장기 거버넌스를 지향하는 커뮤니티 주도 AList 포크입니다.</em></p>
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE"><img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" /></a>
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild"><img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" /></a>
<a href="https://github.com/OpenListTeam/OpenList/discussions"><img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" /></a>
</div>
---
- [English](../README.md) | [中文](./README_cn.md) | [日本語](./README_ja.md) | [Dutch](./README_nl.md) | 한국어 | [Deutsch](./README_de.md) | [Русский](./README_ru.md) | [Français](./README_fr.md) | [Español](./README_es.md) | [العربية](./README_ar.md)
- [Contributing](../CONTRIBUTING.md)
- [CODE OF CONDUCT](../CODE_OF_CONDUCT.md)
- [LICENSE](../LICENSE)
## 면책 조항
OpenList is an open-source project independently maintained by the OpenList Team under the AGPL-3.0 license, with a commitment to code openness and modification transparency.
OpenList has no official association with third-party derivative projects that use similar names, including OpenListApp/OpenListApp or paid proprietary software using the same or similar names.
- All software, code, and services of this project are maintained by the OpenList Team and are freely available on GitHub.
- Project documentation and API services primarily rely on charitable resources provided by Cloudflare. There are currently no paid plans or commercial deployments.
- Downstream projects should not use the "OpenList" name for impersonation or commercial confusion, and must not distribute OpenList-based code as closed source in violation of the AGPL license.
- This software is provided "as is" without warranties. Please comply with applicable laws and regulations when using it.
## 기능
- [x] Multiple storages
- [x] Local storage
- [x] [Aliyundrive](https://www.alipan.com)
- [x] OneDrive / Sharepoint ([Global](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage), [CN](https://portal.partner.microsoftonline.cn), DE, US)
- [x] [189cloud](https://cloud.189.cn) (Personal, Family)
- [x] [GoogleDrive](https://drive.google.com)
- [x] [123pan](https://www.123pan.com)
- [x] [FTP / SFTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol)
- [x] [PikPak](https://www.mypikpak.com)
- [x] [S3](https://aws.amazon.com/s3)
- [x] [Seafile](https://seafile.com)
- [x] [UPYUN Storage Service](https://www.upyun.com/products/file-storage)
- [x] [WebDAV](https://en.wikipedia.org/wiki/WebDAV)
- [x] Teambition([China](https://www.teambition.com), [International](https://us.teambition.com))
- [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, Share)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
- [x] [UC](https://drive.uc.cn)
- [x] [Quark](https://pan.quark.cn)
- [x] [Thunder](https://pan.xunlei.com)
- [x] [Lanzou](https://www.lanzou.com)
- [x] [ILanzou](https://www.ilanzou.com)
- [x] [Google photo](https://photos.google.com)
- [x] [Mega.nz](https://mega.nz)
- [x] [Baidu photo](https://photo.baidu.com)
- [x] [SMB](https://en.wikipedia.org/wiki/Server_Message_Block)
- [x] [115](https://115.com)
- [x] [Cloudreve](https://cloudreve.org)
- [x] [Dropbox](https://www.dropbox.com)
- [x] [FeijiPan](https://www.feijipan.com)
- [x] [dogecloud](https://www.dogecloud.com/product/oss)
- [x] [Azure Blob Storage](https://azure.microsoft.com/products/storage/blobs)
- [x] [Chaoxing](https://www.chaoxing.com)
- [x] [CNB](https://cnb.cool/)
- [x] [Degoo](https://degoo.com)
- [x] [Doubao](https://www.doubao.com)
- [x] [Febbox](https://www.febbox.com)
- [x] [GitHub](https://github.com)
- [x] [OpenList](https://github.com/OpenListTeam/OpenList)
- [x] [Teldrive](https://github.com/tgdrive/teldrive)
- [x] [Weiyun](https://www.weiyun.com)
- [x] [DingTalk Docs](https://alidocs.dingtalk.com/)
- [x] Easy to deploy and out-of-the-box
- [x] File preview (PDF, markdown, code, plain text, ...)
- [x] Image preview in gallery mode
- [x] Video and audio preview, with lyrics and subtitles support
- [x] Office document preview (docx, pptx, xlsx, ...)
- [x] `README.md` preview rendering
- [x] File permalink copy and direct file download
- [x] Dark mode and i18n
- [x] Protected routes, WebDAV, Docker deploy, and Cloudflare Workers proxy
- [x] File/folder package download and web upload operations
- [x] Offline download, cross-storage copy, and multi-thread download acceleration
## 문서
- 📘 [Docs](https://doc.oplist.org)
- 🌏 [CN Mirror](https://doc.oplist.org.cn)
- ⚖️ [Terms of Use](https://doc.oplist.org/terms)
- 🔒 [Privacy Policy](https://doc.oplist.org/privacy)
## 데모
- 🌎 [Global Demo](https://demo.oplist.org)
- 🇨🇳 [CN Demo](https://demo.oplist.org.cn)
## 토론
Please refer to [Discussions](https://github.com/OpenListTeam/OpenList/discussions) for general questions; Issues are for bug reports and feature requests only.
## 후원
[![VPS.Town](https://vps.town/static/images/sponsor.png)](https://vps.town "VPS.Town - Trust, Effortlessly. Your Cloud, Reimagined.")
## 후원자
Thanks to the following donors for their generous support:
- [HisAtri](https://github.com/HisAtri)
- 爱发电用户_7jTh
- suka
## 라이선스
OpenList is open-source software licensed under the [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) license.
## 문의
- [@GitHub](https://github.com/OpenListTeam)
- [Telegram Group](https://t.me/OpenListTeam)
- [Telegram Channel](https://t.me/OpenListOfficial)
## 기여자
We sincerely thank [Xhofe](https://github.com/Xhofe), author of the original project [AlistGo/alist](https://github.com/AlistGo/alist), and all other contributors.
[![Contributors](https://contrib.rocks/image?repo=OpenListTeam/OpenList)](https://github.com/OpenListTeam/OpenList/graphs/contributors)
+174
View File
@@ -0,0 +1,174 @@
<div align="center">
<img src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg" width="128" height="128" alt="logo" />
<p><em>OpenList is een veerkrachtige, langetermijn, door de gemeenschap geleide fork van AList — gebouwd om open source te beschermen tegen op vertrouwen gebaseerde aanvallen.</em></p>
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE"><img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" /></a>
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild"><img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" /></a>
<a href="https://github.com/OpenListTeam/OpenList/discussions"><img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" /></a>
</div>
---
- [English](../README.md) | [中文](./README_cn.md) | [日本語](./README_ja.md) | Dutch | [한국어](./README_ko.md) | [Deutsch](./README_de.md) | [Русский](./README_ru.md) | [Français](./README_fr.md) | [Español](./README_es.md) | [العربية](./README_ar.md)
- [Bijdragen](../CONTRIBUTING.md)
- [Gedragscode](../CODE_OF_CONDUCT.md)
- [Licentie](../LICENSE)
## Disclaimer
OpenList is een open-source project dat onafhankelijk wordt onderhouden door het OpenList Team, volgend op de AGPL-3.0 licentie en toegewijd aan het behouden van volledige code openheid en transparantie van wijzigingen.
We hebben gemerkt dat er in de gemeenschap enkele derde partij projecten zijn verschenen met namen vergelijkbaar met dit project, zoals OpenListApp/OpenListApp, evenals enkele betaalde eigendomssoftware die dezelfde of soortgelijke naamgeving gebruikt. Om verwarring bij gebruikers te voorkomen, verklaren we hierbij:
- OpenList heeft geen officiële associatie met enige derde partij afgeleide projecten.
- Alle software, code en diensten van dit project worden onderhouden door het OpenList Team en zijn gratis beschikbaar op GitHub.
- Projectdocumentatie en API diensten zijn voornamelijk afhankelijk van liefdadigheidsbronnen verstrekt door Cloudflare. Er zijn momenteel geen betaalplannen of commerciële implementaties, en het gebruik van bestaande functies brengt geen kosten met zich mee.
We respecteren de rechten van de gemeenschap voor vrij gebruik en afgeleide ontwikkeling, maar we roepen downstream projecten ook ten zeerste op:
- Mogen niet de "OpenList" naam gebruiken voor namaakpromotie of commercieel gewin;
- Mogen OpenList-gebaseerde code niet distribueren op een closed-source manier of AGPL licentievoorwaarden schenden.
Om een gezonde ecosysteemontwikkeling beter te onderhouden, bevelen we aan:
- Duidelijk de projectbron aangeven en passende open-source licenties kiezen in overeenstemming met de open-source geest;
- Bij commercieel gebruik, vermijd het gebruik van "OpenList" of enige verwarrende naamgeving als projectnaam;
- Als u materialen onder OpenListTeam/Logo moet gebruiken, kunt u deze wijzigen en gebruiken onder naleving van de overeenkomst.
Dank u voor uw ondersteuning en begrip
## Functies
- [x] Meerdere opslagmogelijkheden
- [x] Lokale opslag
- [x] [Aliyundrive](https://www.alipan.com)
- [x] OneDrive / Sharepoint ([Global](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage), [CN](https://portal.partner.microsoftonline.cn), DE, US)
- [x] [189cloud](https://cloud.189.cn) (Persoonlijk, Familie)
- [x] [GoogleDrive](https://drive.google.com)
- [x] [123pan](https://www.123pan.com)
- [x] [FTP / SFTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol)
- [x] [PikPak](https://www.mypikpak.com)
- [x] [S3](https://aws.amazon.com/s3)
- [x] [Seafile](https://seafile.com)
- [x] [UPYUN Storage Service](https://www.upyun.com/products/file-storage)
- [x] [WebDAV](https://en.wikipedia.org/wiki/WebDAV)
- [x] Teambition([China](https://www.teambition.com), [Internationaal](https://us.teambition.com))
- [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, Delen)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
- [x] [UC](https://drive.uc.cn)
- [x] [Quark](https://pan.quark.cn)
- [x] [Thunder](https://pan.xunlei.com)
- [x] [Lanzou](https://www.lanzou.com)
- [x] [ILanzou](https://www.ilanzou.com)
- [x] [Google photo](https://photos.google.com)
- [x] [Mega.nz](https://mega.nz)
- [x] [Baidu photo](https://photo.baidu.com)
- [x] [SMB](https://en.wikipedia.org/wiki/Server_Message_Block)
- [x] [115](https://115.com)
- [x] [Cloudreve](https://cloudreve.org)
- [x] [Dropbox](https://www.dropbox.com)
- [x] [FeijiPan](https://www.feijipan.com)
- [x] [dogecloud](https://www.dogecloud.com/product/oss)
- [x] [Azure Blob Storage](https://azure.microsoft.com/products/storage/blobs)
- [x] [Chaoxing](https://www.chaoxing.com)
- [x] [CNB](https://cnb.cool/)
- [x] [Degoo](https://degoo.com)
- [x] [Doubao](https://www.doubao.com)
- [x] [Febbox](https://www.febbox.com)
- [x] [GitHub](https://github.com)
- [x] [OpenList](https://github.com/OpenListTeam/OpenList)
- [x] [Teldrive](https://github.com/tgdrive/teldrive)
- [x] [Weiyun](https://www.weiyun.com)
- [x] [DingTalk-documenten](https://alidocs.dingtalk.com/)
- [x] Eenvoudig te implementeren en direct te gebruiken
- [x] Bestandsvoorbeeld (PDF, markdown, code, platte tekst, ...)
- [x] Afbeeldingsvoorbeeld in galerijweergave
- [x] Video- en audiovoorbeeld, ondersteuning voor songteksten en ondertitels
- [x] Office-documenten voorbeeld (docx, pptx, xlsx, ...)
- [x] `README.md` voorbeeldweergave
- [x] Permalink kopiëren en direct downloaden van bestanden
- [x] Donkere modus
- [x] I18n
- [x] Beschermde routes (wachtwoordbeveiliging en authenticatie)
- [x] WebDAV
- [x] Docker implementatie
- [x] Cloudflare Workers proxy
- [x] Bestands-/map-pakket download
- [x] Webupload (bezoekers kunnen uploaden toestaan), verwijderen, map aanmaken, hernoemen, verplaatsen en kopiëren
- [x] Offline download
- [x] Bestanden kopiëren tussen twee opslaglocaties
- [x] Multi-thread downloadversnelling voor enkelvoudige download/stream
## Documentatie
- 📘 [Documentatie](https://doc.oplist.org)
- 🌏 [CN Mirror](https://doc.oplist.org.cn)
- ⚖️ [Gebruiksvoorwaarden](https://doc.oplist.org/terms)
- 🔒 [Privacybeleid](https://doc.oplist.org/privacy)
## Demo
- 🌎 [Global Demo](https://demo.oplist.org)
- 🇨🇳 [CN Demo](https://demo.oplist.org.cn)
## Discussie
Stel algemene vragen in [*Discussions*](https://github.com/OpenListTeam/OpenList/discussions), ***Issues* zijn alleen voor bugmeldingen en feature requests.**
## Sponsoren
[![VPS.Town](https://vps.town/static/images/sponsor.png)](https://vps.town "VPS.Town - Trust, Effortlessly. Your Cloud, Reimagined.")
## Donatie Bijdragers
Dank aan de volgende donateurs voor hun steun:
- [HisAtri](https://github.com/HisAtri)
- 爱发电用户_7jTh
- suka
## Licentie
`OpenList` is open-source software onder de [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) licentie.
## Disclaimer
- Dit project is gratis en open-source software, ontworpen om het delen van bestanden via netdisks te vergemakkelijken, voornamelijk bedoeld ter ondersteuning van het downloaden en leren van de programmeertaal Go.
- Houd u bij het gebruik van deze software aan alle toepasselijke wetten en voorschriften. Elk misbruik is ten strengste verboden.
- De software is gebaseerd op officiële SDK's of API's zonder enige wijziging, verstoring of beïnvloeding van hun gedrag.
- Het voert alleen HTTP 302-omleidingen of verkeersdoorsturing uit en onderschept, slaat of wijzigt geen gebruikersgegevens.
- Dit project is niet gelieerd aan enig officieel platform of dienstverlener.
- De software wordt geleverd "zoals deze is", zonder enige vorm van garantie, expliciet of impliciet, inclusief maar niet beperkt tot garanties van verkoopbaarheid of geschiktheid voor een bepaald doel.
- De beheerders zijn niet aansprakelijk voor enige directe of indirecte schade die voortvloeit uit het gebruik van of het onvermogen om deze software te gebruiken.
- U bent zelf verantwoordelijk voor alle risico's die gepaard gaan met het gebruik van deze software, inclusief maar niet beperkt tot accountblokkades of downloadbeperkingen.
- Dit project valt onder de [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) licentie. Zie het [LICENSE](../LICENSE) bestand voor details.
## Contact
- [@GitHub](https://github.com/OpenListTeam)
- [Telegram Groep](https://t.me/OpenListTeam)
- [Telegram Kanaal](https://t.me/OpenListOfficial)
## Bijdragers
Wij danken de auteur [Xhofe](https://github.com/Xhofe) van het originele project [AlistGo/alist](https://github.com/AlistGo/alist) en alle andere bijdragers.
Dank aan deze geweldige mensen:
[![Contributors](https://contrib.rocks/image?repo=OpenListTeam/OpenList)](https://github.com/OpenListTeam/OpenList/graphs/contributors)
+136
View File
@@ -0,0 +1,136 @@
<div align="center">
<img src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg" width="128" height="128" alt="logo" />
<p><em>OpenList — устойчивый, управляемый сообществом форк AList с долгосрочным управлением, созданный для защиты open source от атак, основанных на доверии.</em></p>
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE"><img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" /></a>
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild"><img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" /></a>
<a href="https://github.com/OpenListTeam/OpenList/discussions"><img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" /></a>
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" /></a>
</div>
---
- [English](../README.md) | [中文](./README_cn.md) | [日本語](./README_ja.md) | [Dutch](./README_nl.md) | [한국어](./README_ko.md) | [Deutsch](./README_de.md) | Русский | [Français](./README_fr.md) | [Español](./README_es.md) | [العربية](./README_ar.md)
- [Contributing](../CONTRIBUTING.md)
- [CODE OF CONDUCT](../CODE_OF_CONDUCT.md)
- [LICENSE](../LICENSE)
## Отказ от ответственности
OpenList is an open-source project independently maintained by the OpenList Team under the AGPL-3.0 license, with a commitment to code openness and modification transparency.
OpenList has no official association with third-party derivative projects that use similar names, including OpenListApp/OpenListApp or paid proprietary software using the same or similar names.
- All software, code, and services of this project are maintained by the OpenList Team and are freely available on GitHub.
- Project documentation and API services primarily rely on charitable resources provided by Cloudflare. There are currently no paid plans or commercial deployments.
- Downstream projects should not use the "OpenList" name for impersonation or commercial confusion, and must not distribute OpenList-based code as closed source in violation of the AGPL license.
- This software is provided "as is" without warranties. Please comply with applicable laws and regulations when using it.
## Возможности
- [x] Multiple storages
- [x] Local storage
- [x] [Aliyundrive](https://www.alipan.com)
- [x] OneDrive / Sharepoint ([Global](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage), [CN](https://portal.partner.microsoftonline.cn), DE, US)
- [x] [189cloud](https://cloud.189.cn) (Personal, Family)
- [x] [GoogleDrive](https://drive.google.com)
- [x] [123pan](https://www.123pan.com)
- [x] [FTP / SFTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol)
- [x] [PikPak](https://www.mypikpak.com)
- [x] [S3](https://aws.amazon.com/s3)
- [x] [Seafile](https://seafile.com)
- [x] [UPYUN Storage Service](https://www.upyun.com/products/file-storage)
- [x] [WebDAV](https://en.wikipedia.org/wiki/WebDAV)
- [x] Teambition([China](https://www.teambition.com), [International](https://us.teambition.com))
- [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, Share)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
- [x] [UC](https://drive.uc.cn)
- [x] [Quark](https://pan.quark.cn)
- [x] [Thunder](https://pan.xunlei.com)
- [x] [Lanzou](https://www.lanzou.com)
- [x] [ILanzou](https://www.ilanzou.com)
- [x] [Google photo](https://photos.google.com)
- [x] [Mega.nz](https://mega.nz)
- [x] [Baidu photo](https://photo.baidu.com)
- [x] [SMB](https://en.wikipedia.org/wiki/Server_Message_Block)
- [x] [115](https://115.com)
- [x] [Cloudreve](https://cloudreve.org)
- [x] [Dropbox](https://www.dropbox.com)
- [x] [FeijiPan](https://www.feijipan.com)
- [x] [dogecloud](https://www.dogecloud.com/product/oss)
- [x] [Azure Blob Storage](https://azure.microsoft.com/products/storage/blobs)
- [x] [Chaoxing](https://www.chaoxing.com)
- [x] [CNB](https://cnb.cool/)
- [x] [Degoo](https://degoo.com)
- [x] [Doubao](https://www.doubao.com)
- [x] [Febbox](https://www.febbox.com)
- [x] [GitHub](https://github.com)
- [x] [OpenList](https://github.com/OpenListTeam/OpenList)
- [x] [Teldrive](https://github.com/tgdrive/teldrive)
- [x] [Weiyun](https://www.weiyun.com)
- [x] [DingTalk Docs](https://alidocs.dingtalk.com/)
- [x] Easy to deploy and out-of-the-box
- [x] File preview (PDF, markdown, code, plain text, ...)
- [x] Image preview in gallery mode
- [x] Video and audio preview, with lyrics and subtitles support
- [x] Office document preview (docx, pptx, xlsx, ...)
- [x] `README.md` preview rendering
- [x] File permalink copy and direct file download
- [x] Dark mode and i18n
- [x] Protected routes, WebDAV, Docker deploy, and Cloudflare Workers proxy
- [x] File/folder package download and web upload operations
- [x] Offline download, cross-storage copy, and multi-thread download acceleration
## Документация
- 📘 [Docs](https://doc.oplist.org)
- 🌏 [CN Mirror](https://doc.oplist.org.cn)
- ⚖️ [Terms of Use](https://doc.oplist.org/terms)
- 🔒 [Privacy Policy](https://doc.oplist.org/privacy)
## Демо
- 🌎 [Global Demo](https://demo.oplist.org)
- 🇨🇳 [CN Demo](https://demo.oplist.org.cn)
## Обсуждение
Please refer to [Discussions](https://github.com/OpenListTeam/OpenList/discussions) for general questions; Issues are for bug reports and feature requests only.
## Спонсор
[![VPS.Town](https://vps.town/static/images/sponsor.png)](https://vps.town "VPS.Town - Trust, Effortlessly. Your Cloud, Reimagined.")
## Доноры
Thanks to the following donors for their generous support:
- [HisAtri](https://github.com/HisAtri)
- 爱发电用户_7jTh
- suka
## Лицензия
OpenList is open-source software licensed under the [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) license.
## Связаться с нами
- [@GitHub](https://github.com/OpenListTeam)
- [Telegram Group](https://t.me/OpenListTeam)
- [Telegram Channel](https://t.me/OpenListOfficial)
## Участники
We sincerely thank [Xhofe](https://github.com/Xhofe), author of the original project [AlistGo/alist](https://github.com/AlistGo/alist), and all other contributors.
[![Contributors](https://contrib.rocks/image?repo=OpenListTeam/OpenList)](https://github.com/OpenListTeam/OpenList/graphs/contributors)
-139
View File
@@ -1,139 +0,0 @@
<div align="center">
<a href="https://alist.nn.ci"><img width="100px" alt="logo" src="https://cdn.jsdelivr.net/gh/alist-org/logo@main/logo.svg"/></a>
<p><em>🗂一个支持多存储的文件列表程序,使用 Gin 和 Solidjs。</em></p>
<div>
<a href="https://goreportcard.com/report/github.com/alist-org/alist/v3">
<img src="https://goreportcard.com/badge/github.com/alist-org/alist/v3" alt="latest version" />
</a>
<a href="https://github.com/alist-org/alist/blob/main/LICENSE">
<img src="https://img.shields.io/github/license/Xhofe/alist" alt="License" />
</a>
<a href="https://github.com/alist-org/alist/actions?query=workflow%3ABuild">
<img src="https://img.shields.io/github/actions/workflow/status/Xhofe/alist/build.yml?branch=main" alt="Build status" />
</a>
<a href="https://github.com/alist-org/alist/releases">
<img src="https://img.shields.io/github/release/Xhofe/alist" alt="latest version" />
</a>
<a title="Crowdin" target="_blank" href="https://crwd.in/alist">
<img src="https://badges.crowdin.net/alist/localized.svg">
</a>
</div>
<div>
<a href="https://github.com/alist-org/alist/discussions">
<img src="https://img.shields.io/github/discussions/Xhofe/alist?color=%23ED8936" alt="discussions" />
</a>
<a href="https://discord.gg/F4ymsH4xv2">
<img src="https://img.shields.io/discord/1018870125102895134?logo=discord" alt="discussions" />
</a>
<a href="https://github.com/alist-org/alist/releases">
<img src="https://img.shields.io/github/downloads/Xhofe/alist/total?color=%239F7AEA&logo=github" alt="Downloads" />
</a>
<a href="https://hub.docker.com/r/xhofe/alist">
<img src="https://img.shields.io/docker/pulls/xhofe/alist?color=%2348BB78&logo=docker&label=pulls" alt="Downloads" />
</a>
<a href="https://alist.nn.ci/zh/guide/sponsor.html">
<img src="https://img.shields.io/badge/%24-sponsor-F87171.svg" alt="sponsor" />
</a>
</div>
</div>
---
[English](./README.md) | 中文 | [日本語](./README_ja.md) | [Contributing](./CONTRIBUTING.md) | [CODE_OF_CONDUCT](./CODE_OF_CONDUCT.md)
## 功能
- [x] 多种存储
- [x] 本地存储
- [x] [阿里云盘](https://www.alipan.com/)
- [x] OneDrive / Sharepoint([国际版](https://www.office.com/), [世纪互联](https://portal.partner.microsoftonline.cn),de,us)
- [x] [天翼云盘](https://cloud.189.cn) (个人云, 家庭云)
- [x] [GoogleDrive](https://drive.google.com/)
- [x] [123云盘](https://www.123pan.com/)
- [x] FTP / SFTP
- [x] [PikPak](https://www.mypikpak.com/)
- [x] [S3](https://aws.amazon.com/cn/s3/)
- [x] [Seafile](https://seafile.com/)
- [x] [又拍云对象存储](https://www.upyun.com/products/file-storage)
- [x] WebDav(支持无API的OneDrive/SharePoint)
- [x] Teambition([中国](https://www.teambition.com/ ),[国际](https://us.teambition.com/ ))
- [x] [分秒帧](https://www.mediatrack.cn/)
- [x] [和彩云](https://yun.139.com/) (个人云, 家庭云)
- [x] [Yandex.Disk](https://disk.yandex.com/)
- [x] [百度网盘](http://pan.baidu.com/)
- [x] [UC网盘](https://drive.uc.cn)
- [x] [夸克网盘](https://pan.quark.cn)
- [x] [迅雷网盘](https://pan.xunlei.com)
- [x] [蓝奏云](https://www.lanzou.com/)
- [x] [蓝奏云优享版](https://www.ilanzou.com/)
- [x] [阿里云盘分享](https://www.alipan.com/)
- [x] [谷歌相册](https://photos.google.com/)
- [x] [Mega.nz](https://mega.nz)
- [x] [一刻相册](https://photo.baidu.com/)
- [x] SMB
- [x] [115](https://115.com/)
- [X] Cloudreve
- [x] [Dropbox](https://www.dropbox.com/)
- [x] [飞机盘](https://www.feijipan.com/)
- [x] [多吉云](https://www.dogecloud.com/product/oss)
- [x] 部署方便,开箱即用
- [x] 文件预览(PDF、markdown、代码、纯文本……)
- [x] 画廊模式下的图像预览
- [x] 视频和音频预览,支持歌词和字幕
- [x] Office 文档预览(docx、pptx、xlsx、...)
- [x] `README.md` 预览渲染
- [x] 文件永久链接复制和直接文件下载
- [x] 黑暗模式
- [x] 国际化
- [x] 受保护的路由(密码保护和身份验证)
- [x] WebDav (具体见 https://alist.nn.ci/zh/guide/webdav.html)
- [x] [Docker 部署](https://hub.docker.com/r/xhofe/alist)
- [x] Cloudflare workers 中转
- [x] 文件/文件夹打包下载
- [x] 网页上传(可以允许访客上传),删除,新建文件夹,重命名,移动,复制
- [x] 离线下载
- [x] 跨存储复制文件
- [x] 单线程下载/串流的多线程下载加速
## 文档
<https://alist.nn.ci/zh/>
## Demo
<https://al.nn.ci>
## 讨论
一般问题请到[讨论论坛](https://github.com/alist-org/alist/discussions) ,**issue仅针对错误报告和功能请求。**
## 赞助
AList 是一个开源软件,如果你碰巧喜欢这个项目,并希望我继续下去,请考虑赞助我或提供一个单一的捐款!感谢所有的爱和支持:https://alist.nn.ci/zh/guide/sponsor.html
### 特别赞助
- [VidHub](https://apps.apple.com/app/apple-store/id1659622164?pt=118612019&ct=alist&mt=8) - 苹果生态下优雅的网盘视频播放器,iPhone,iPad,Mac,Apple TV全平台支持。
- [亚洲云](https://www.asiayun.com/aff/QQCOOQKZ) - 高防服务器|服务器租用|福州高防|广东电信|香港服务器|美国服务器|海外服务器 - 国内靠谱的企业级云计算服务提供商 (国内API服务器赞助)
- [找资源](http://zhaoziyuan2.cc/) - 阿里云盘资源搜索引擎
## 贡献者
Thanks goes to these wonderful people:
[![Contributors](http://contrib.nn.ci/api?repo=alist-org/alist&repo=alist-org/alist-web&repo=alist-org/docs)](https://github.com/alist-org/alist/graphs/contributors)
## 许可
`AList` 是在 AGPL-3.0 许可下许可的开源软件。
## 免责声明
- 本程序为免费开源项目,旨在分享网盘文件,方便下载以及学习golang,使用时请遵守相关法律法规,请勿滥用;
- 本程序通过调用官方sdk/接口实现,无破坏官方接口行为;
- 本程序仅做302重定向/流量转发,不拦截、存储、篡改任何用户数据;
- 在使用本程序之前,你应了解并承担相应的风险,包括但不限于账号被ban,下载限速等,与本程序无关;
- 如有侵权,请通过[邮件](mailto:i@nn.ci)与我联系,会及时处理。
---
> [@博客](https://nn.ci/) · [@GitHub](https://github.com/alist-org) · [@Telegram群](https://t.me/alist_chat) · [@Discord](https://discord.gg/F4ymsH4xv2)
-141
View File
@@ -1,141 +0,0 @@
<div align="center">
<a href="https://alist.nn.ci"><img width="100px" alt="logo" src="https://cdn.jsdelivr.net/gh/alist-org/logo@main/logo.svg"/></a>
<p><em>🗂️Gin と Solidjs による、複数のストレージをサポートするファイルリストプログラム。</em></p>
<div>
<a href="https://goreportcard.com/report/github.com/alist-org/alist/v3">
<img src="https://goreportcard.com/badge/github.com/alist-org/alist/v3" alt="latest version" />
</a>
<a href="https://github.com/alist-org/alist/blob/main/LICENSE">
<img src="https://img.shields.io/github/license/Xhofe/alist" alt="License" />
</a>
<a href="https://github.com/alist-org/alist/actions?query=workflow%3ABuild">
<img src="https://img.shields.io/github/actions/workflow/status/Xhofe/alist/build.yml?branch=main" alt="Build status" />
</a>
<a href="https://github.com/alist-org/alist/releases">
<img src="https://img.shields.io/github/release/Xhofe/alist" alt="latest version" />
</a>
<a title="Crowdin" target="_blank" href="https://crwd.in/alist">
<img src="https://badges.crowdin.net/alist/localized.svg">
</a>
</div>
<div>
<a href="https://github.com/alist-org/alist/discussions">
<img src="https://img.shields.io/github/discussions/Xhofe/alist?color=%23ED8936" alt="discussions" />
</a>
<a href="https://discord.gg/F4ymsH4xv2">
<img src="https://img.shields.io/discord/1018870125102895134?logo=discord" alt="discussions" />
</a>
<a href="https://github.com/alist-org/alist/releases">
<img src="https://img.shields.io/github/downloads/Xhofe/alist/total?color=%239F7AEA&logo=github" alt="Downloads" />
</a>
<a href="https://hub.docker.com/r/xhofe/alist">
<img src="https://img.shields.io/docker/pulls/xhofe/alist?color=%2348BB78&logo=docker&label=pulls" alt="Downloads" />
</a>
<a href="https://alist.nn.ci/guide/sponsor.html">
<img src="https://img.shields.io/badge/%24-sponsor-F87171.svg" alt="sponsor" />
</a>
</div>
</div>
---
[English](./README.md) | [中文](./README_cn.md) | 日本語 | [Contributing](./CONTRIBUTING.md) | [CODE_OF_CONDUCT](./CODE_OF_CONDUCT.md)
## 特徴
- [x] マルチストレージ
- [x] ローカルストレージ
- [x] [Aliyundrive](https://www.alipan.com/)
- [x] OneDrive / Sharepoint ([グローバル](https://www.office.com/), [cn](https://portal.partner.microsoftonline.cn),de,us)
- [x] [189cloud](https://cloud.189.cn) (Personal, Family)
- [x] [GoogleDrive](https://drive.google.com/)
- [x] [123pan](https://www.123pan.com/)
- [x] FTP / SFTP
- [x] [PikPak](https://www.mypikpak.com/)
- [x] [S3](https://aws.amazon.com/s3/)
- [x] [Seafile](https://seafile.com/)
- [x] [UPYUN Storage Service](https://www.upyun.com/products/file-storage)
- [x] WebDav(Support OneDrive/SharePoint without API)
- [x] Teambition([China](https://www.teambition.com/ ),[International](https://us.teambition.com/ ))
- [x] [Mediatrack](https://www.mediatrack.cn/)
- [x] [139yun](https://yun.139.com/) (Personal, Family)
- [x] [YandexDisk](https://disk.yandex.com/)
- [x] [BaiduNetdisk](http://pan.baidu.com/)
- [x] [Terabox](https://www.terabox.com/main)
- [x] [UC](https://drive.uc.cn)
- [x] [Quark](https://pan.quark.cn)
- [x] [Thunder](https://pan.xunlei.com)
- [x] [Lanzou](https://www.lanzou.com/)
- [x] [ILanzou](https://www.ilanzou.com/)
- [x] [Aliyundrive share](https://www.alipan.com/)
- [x] [Google photo](https://photos.google.com/)
- [x] [Mega.nz](https://mega.nz)
- [x] [Baidu photo](https://photo.baidu.com/)
- [x] SMB
- [x] [115](https://115.com/)
- [X] Cloudreve
- [x] [Dropbox](https://www.dropbox.com/)
- [x] [FeijiPan](https://www.feijipan.com/)
- [x] [dogecloud](https://www.dogecloud.com/product/oss)
- [x] デプロイが簡単で、すぐに使える
- [x] ファイルプレビュー (PDF, マークダウン, コード, プレーンテキスト, ...)
- [x] ギャラリーモードでの画像プレビュー
- [x] ビデオとオーディオのプレビュー、歌詞と字幕のサポート
- [x] Office ドキュメントのプレビュー (docx, pptx, xlsx, ...)
- [x] `README.md` のプレビューレンダリング
- [x] ファイルのパーマリンクコピーと直接ダウンロード
- [x] ダークモード
- [x] 国際化
- [x] 保護されたルート (パスワード保護と認証)
- [x] WebDav (詳細は https://alist.nn.ci/guide/webdav.html を参照)
- [x] [Docker デプロイ](https://hub.docker.com/r/xhofe/alist)
- [x] Cloudflare ワーカープロキシ
- [x] ファイル/フォルダパッケージのダウンロード
- [x] ウェブアップロード(訪問者にアップロードを許可できる), 削除, mkdir, 名前変更, 移動, コピー
- [x] オフラインダウンロード
- [x] 二つのストレージ間でファイルをコピー
- [x] シングルスレッドのダウンロード/ストリーム向けのマルチスレッド ダウンロード アクセラレーション
## ドキュメント
<https://alist.nn.ci/>
## デモ
<https://al.nn.ci>
## ディスカッション
一般的なご質問は[ディスカッションフォーラム](https://github.com/alist-org/alist/discussions)をご利用ください。**問題はバグレポートと機能リクエストのみです。**
## スポンサー
AList はオープンソースのソフトウェアです。もしあなたがこのプロジェクトを気に入ってくださり、続けて欲しいと思ってくださるなら、ぜひスポンサーになってくださるか、1口でも寄付をしてくださるようご検討ください!すべての愛とサポートに感謝します:
https://alist.nn.ci/guide/sponsor.html
### スペシャルスポンサー
- [VidHub](https://apps.apple.com/app/apple-store/id1659622164?pt=118612019&ct=alist&mt=8) - An elegant cloud video player within the Apple ecosystem. Support for iPhone, iPad, Mac, and Apple TV.
- [亚洲云](https://www.asiayun.com/aff/QQCOOQKZ) - 高防服务器|服务器租用|福州高防|广东电信|香港服务器|美国服务器|海外服务器 - 国内靠谱的企业级云计算服务提供商 (sponsored Chinese API server)
- [找资源](http://zhaoziyuan2.cc/) - 阿里云盘资源搜索引擎
## コントリビューター
これらの素晴らしい人々に感謝します:
[![Contributors](http://contrib.nn.ci/api?repo=alist-org/alist&repo=alist-org/alist-web&repo=alist-org/docs)](https://github.com/alist-org/alist/graphs/contributors)
## ライセンス
`AList` は AGPL-3.0 ライセンスの下でライセンスされたオープンソースソフトウェアです。
## 免責事項
- このプログラムはフリーでオープンソースのプロジェクトです。ネットワークディスク上でファイルを共有するように設計されており、golang のダウンロードや学習に便利です。利用にあたっては関連法規を遵守し、悪用しないようお願いします;
- このプログラムは、公式インターフェースの動作を破壊することなく、公式 sdk/インターフェースを呼び出すことで実装されています;
- このプログラムは、302リダイレクト/トラフィック転送のみを行い、いかなるユーザーデータも傍受、保存、改ざんしません;
- このプログラムを使用する前に、アカウントの禁止、ダウンロード速度の制限など、対応するリスクを理解し、負担する必要があります;
- もし侵害があれば、[メール](mailto:i@nn.ci)で私に連絡してください。
---
> [@Blog](https://nn.ci/) · [@GitHub](https://github.com/alist-org) · [@TelegramGroup](https://t.me/alist_chat) · [@Discord](https://discord.gg/F4ymsH4xv2)
+89
View File
@@ -0,0 +1,89 @@
# Security Policy
## Supported Versions
Only the latest stable release receives security patches. We strongly recommend always keeping OpenList up to date.
| Version | Supported |
| -------------------- | ------------------ |
| Latest stable (v4.x) | :white_check_mark: |
| Older versions | :x: |
## Reporting a Vulnerability
**Please do NOT report security vulnerabilities through public GitHub Issues.**
If you discover a security vulnerability in OpenList, please report it responsibly by using one of the following channels:
- **GitHub Private Security Advisory** (preferred): [Submit here](https://github.com/OpenListTeam/OpenList/security/advisories/new)
- **Telegram**: Contact a maintainer privately via [@OpenListTeam](https://t.me/OpenListTeam)
When reporting, please include as much of the following as possible:
- A description of the vulnerability and its potential impact
- The affected version(s)
- Step-by-step instructions to reproduce the issue
- Any proof-of-concept code or screenshots (if applicable)
- Suggested mitigation or fix (optional but appreciated)
## Security Best Practices for Users
To keep your OpenList instance secure:
- Always update to the latest release.
- Use a strong, unique admin password and change it after first login.
- Enable HTTPS (TLS) for your deployment — do **not** expose OpenList over plain HTTP on the public internet.
- Limit exposed ports using a reverse proxy (e.g., Nginx, Caddy).
- Set up access controls and avoid enabling guest access unless necessary.
- Regularly review mounted storage permissions and revoke unused API tokens.
- When using Docker, avoid running the container as root if possible.
## Acknowledgments
We sincerely thank all security researchers and community members who responsibly disclose vulnerabilities and help make OpenList safer for everyone.
---
# 安全政策
## 支持的版本
我们仅对最新稳定版本提供安全补丁。强烈建议始终保持 OpenList 为最新版本。
| 版本 | 是否支持 |
| ------------------ | ------------------ |
| 最新稳定版(v4.x) | :white_check_mark: |
| 旧版本 | :x: |
## 报告漏洞
**请勿通过公开的 GitHub Issues 报告安全漏洞。**
如果您在 OpenList 中发现安全漏洞,请通过以下渠道之一负责任地进行报告:
- **GitHub 私密安全公告**(推荐):[点击提交](https://github.com/OpenListTeam/OpenList/security/advisories/new)
- **Telegram**:通过 [@OpenListTeam](https://t.me/OpenListTeam) 私信联系维护者
报告时,请尽量提供以下信息:
- 漏洞描述及其潜在影响
- 受影响的版本
- 复现问题的详细步骤
- 概念验证代码或截图(如有)
- 建议的缓解措施或修复方案(可选,但非常欢迎)
## 用户安全最佳实践
为保障您的 OpenList 实例安全:
- 始终更新至最新版本。
- 使用强且唯一的管理员密码,并在首次登录后立即修改。
- 为您的部署启用 HTTPS(TLS)—— **请勿**在公网上以明文 HTTP 方式暴露 OpenList。
- 使用反向代理(如 Nginx、Caddy)限制对外暴露的端口。
- 配置访问控制,非必要情况下不要开启访客访问。
- 定期检查已挂载存储的权限,并撤销未使用的 API 令牌。
- 使用 Docker 部署时,尽可能避免以 root 用户运行容器。
## 致谢
我们衷心感谢所有负责任地披露漏洞、帮助 OpenList 变得更加安全的安全研究人员和社区成员。
+506 -108
View File
@@ -1,44 +1,127 @@
appName="alist"
set -e
appName="openlist"
builtAt="$(date +'%F %T %z')"
goVersion=$(go version | sed 's/go version //')
gitAuthor="Xhofe <i@nn.ci>"
gitAuthor="The OpenList Projects Contributors <noreply@oplist.org>"
gitCommit=$(git log --pretty=format:"%h" -1)
# Set frontend repository, default to OpenListTeam/OpenList-Frontend
frontendRepo="${FRONTEND_REPO:-OpenListTeam/OpenList-Frontend}"
githubAuthArgs=""
if [ -n "$GITHUB_TOKEN" ]; then
githubAuthArgs="--header \"Authorization: Bearer $GITHUB_TOKEN\""
fi
# Check for lite parameter
useLite=false
if [[ "$*" == *"lite"* ]]; then
useLite=true
fi
if [ "$1" = "dev" ]; then
version="dev"
webVersion="dev"
webVersion="rolling"
elif [ "$1" = "beta" ]; then
version="beta"
webVersion="rolling"
else
git tag -d beta
version=$(git describe --abbrev=0 --tags)
webVersion=$(wget -qO- -t1 -T2 "https://api.github.com/repos/alist-org/alist-web/releases/latest" | grep "tag_name" | head -n 1 | awk -F ":" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g')
git tag -d beta || true
# Always true if there's no tag
version=$(git describe --abbrev=0 --tags 2>/dev/null || echo "v0.0.0")
webVersion=$(eval "curl -fsSL --max-time 2 $githubAuthArgs \"https://api.github.com/repos/$frontendRepo/releases/latest\"" | grep "tag_name" | head -n 1 | awk -F ":" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g')
fi
echo "backend version: $version"
echo "frontend version: $webVersion"
if [ "$useLite" = true ]; then
echo "using lite frontend"
else
echo "using standard frontend"
fi
ldflags="\
-w -s \
-X 'github.com/alist-org/alist/v3/internal/conf.BuiltAt=$builtAt' \
-X 'github.com/alist-org/alist/v3/internal/conf.GoVersion=$goVersion' \
-X 'github.com/alist-org/alist/v3/internal/conf.GitAuthor=$gitAuthor' \
-X 'github.com/alist-org/alist/v3/internal/conf.GitCommit=$gitCommit' \
-X 'github.com/alist-org/alist/v3/internal/conf.Version=$version' \
-X 'github.com/alist-org/alist/v3/internal/conf.WebVersion=$webVersion' \
-X 'github.com/OpenListTeam/OpenList/v4/internal/conf.BuiltAt=$builtAt' \
-X 'github.com/OpenListTeam/OpenList/v4/internal/conf.GitAuthor=$gitAuthor' \
-X 'github.com/OpenListTeam/OpenList/v4/internal/conf.GitCommit=$gitCommit' \
-X 'github.com/OpenListTeam/OpenList/v4/internal/conf.Version=$version' \
-X 'github.com/OpenListTeam/OpenList/v4/internal/conf.WebVersion=$webVersion' \
"
FetchWebDev() {
curl -L https://codeload.github.com/alist-org/web-dist/tar.gz/refs/heads/dev -o web-dist-dev.tar.gz
tar -zxvf web-dist-dev.tar.gz
rm -rf public/dist
mv -f web-dist-dev/dist public
rm -rf web-dist-dev web-dist-dev.tar.gz
# Keep sqlite driver tag selection centralized to avoid target drift.
GetBuildTagsForTarget() {
local target="$1"
case "$target" in
linux-loong64|linux-mips|linux-mips64|linux-mips64le|linux-mipsle|linux-musl-loong64|linux-musl-mips|linux-musl-mips64|linux-musl-mips64le|linux-musl-mipsle|windows-386|windows7-386|windows7-amd64)
echo "jsoniter,sqlite_cgo_compat"
;;
*)
echo "jsoniter"
;;
esac
}
# Keep musl static link flags centralized for all musl build paths.
GetMuslStaticLdflags() {
echo "-linkmode external -extldflags '-static -fpic' $ldflags"
}
# Fail fast if a musl build artifact is not fully static.
AssertStaticBinary() {
local binary="$1"
if [ ! -f "$binary" ]; then
echo "Error: binary not found: $binary"
return 1
fi
if command -v readelf >/dev/null 2>&1; then
if readelf -l "$binary" 2>/dev/null | grep -q "Requesting program interpreter"; then
echo "Error: binary is not fully static: $binary"
readelf -l "$binary" | grep "Requesting program interpreter" || true
return 1
fi
return 0
fi
if command -v file >/dev/null 2>&1; then
if file "$binary" | grep -qi "dynamically linked"; then
echo "Error: binary is dynamically linked: $binary"
file "$binary"
return 1
fi
return 0
fi
echo "Warning: readelf/file not found, skip static verification for $binary"
return 0
}
FetchWebRolling() {
pre_release_json=$(eval "curl -fsSL --max-time 2 $githubAuthArgs -H \"Accept: application/vnd.github.v3+json\" \"https://api.github.com/repos/$frontendRepo/releases/tags/edge\"")
pre_release_assets=$(echo "$pre_release_json" | jq -r '.assets[].browser_download_url')
# There is no lite for rolling
pre_release_tar_url=$(echo "$pre_release_assets" | grep "openlist-frontend-dist" | grep -v "lite" | grep "\.tar\.gz$")
curl -fsSL "$pre_release_tar_url" -o dist.tar.gz
rm -rf public/dist && mkdir -p public/dist
tar -zxvf dist.tar.gz -C public/dist
rm -rf dist.tar.gz
}
FetchWebRelease() {
curl -L https://github.com/alist-org/alist-web/releases/latest/download/dist.tar.gz -o dist.tar.gz
tar -zxvf dist.tar.gz
rm -rf public/dist
mv -f dist public
release_json=$(eval "curl -fsSL --max-time 2 $githubAuthArgs -H \"Accept: application/vnd.github.v3+json\" \"https://api.github.com/repos/$frontendRepo/releases/latest\"")
release_assets=$(echo "$release_json" | jq -r '.assets[].browser_download_url')
if [ "$useLite" = true ]; then
release_tar_url=$(echo "$release_assets" | grep "openlist-frontend-dist-lite" | grep "\.tar\.gz$")
else
release_tar_url=$(echo "$release_assets" | grep "openlist-frontend-dist" | grep -v "lite" | grep "\.tar\.gz$")
fi
curl -fsSL "$release_tar_url" -o dist.tar.gz
rm -rf public/dist && mkdir -p public/dist
tar -zxvf dist.tar.gz -C public/dist
rm -rf dist.tar.gz
}
@@ -54,15 +137,54 @@ BuildWinArm64() {
go build -o "$1" -ldflags="$ldflags" -tags=jsoniter .
}
BuildWin7() {
# Setup Win7 Go compiler (patched version that supports Windows 7)
go_version=$(go version | grep -o 'go[0-9]\+\.[0-9]\+\.[0-9]\+' | sed 's/go//')
echo "Detected Go version: $go_version"
curl -fsSL --retry 3 -o go-win7.zip -H "Authorization: Bearer $GITHUB_TOKEN" \
"https://github.com/XTLS/go-win7/releases/download/patched-${go_version}/go-for-win7-linux-amd64.zip"
rm -rf go-win7
unzip go-win7.zip -d go-win7
rm go-win7.zip
# Set permissions for all wrapper files
chmod +x ./wrapper/zcc-win7
chmod +x ./wrapper/zcxx-win7
chmod +x ./wrapper/zcc-win7-386
chmod +x ./wrapper/zcxx-win7-386
# Build for both 386 and amd64 architectures
for arch in "386" "amd64"; do
echo "building for windows7-${arch}"
build_tags=$(GetBuildTagsForTarget "windows7-${arch}")
export GOOS=windows
export GOARCH=${arch}
export CGO_ENABLED=1
# Use architecture-specific wrapper files
if [ "$arch" = "386" ]; then
export CC=$(pwd)/wrapper/zcc-win7-386
export CXX=$(pwd)/wrapper/zcxx-win7-386
else
export CC=$(pwd)/wrapper/zcc-win7
export CXX=$(pwd)/wrapper/zcxx-win7
fi
# Use the patched Go compiler for Win7 compatibility
$(pwd)/go-win7/bin/go build -o "${1}-${arch}.exe" -ldflags="$ldflags" -tags="$build_tags" .
done
}
BuildDev() {
rm -rf .git/
mkdir -p "dist"
muslflags="--extldflags '-static -fpic' $ldflags"
BASE="https://musl.nn.ci/"
muslflags="$(GetMuslStaticLdflags)"
BASE="https://github.com/OpenListTeam/musl-compilers/releases/latest/download/"
FILES=(x86_64-linux-musl-cross aarch64-linux-musl-cross)
for i in "${FILES[@]}"; do
url="${BASE}${i}.tgz"
curl -L -o "${i}.tgz" "${url}"
curl -fsSL -o "${i}.tgz" "${url}"
sudo tar xf "${i}.tgz" --strip-components 1 -C /usr/local
done
OS_ARCHES=(linux-musl-amd64 linux-musl-arm64)
@@ -75,29 +197,30 @@ BuildDev() {
export GOARCH=${os_arch##*-}
export CC=${cgo_cc}
export CGO_ENABLED=1
go build -o ./dist/$appName-$os_arch -ldflags="$muslflags" -tags=jsoniter .
CGO_LDFLAGS="-static" go build -o ./dist/$appName-$os_arch -ldflags="$muslflags" -tags=jsoniter .
AssertStaticBinary "./dist/$appName-$os_arch"
done
xgo -targets=windows/amd64,darwin/amd64,darwin/arm64 -out "$appName" -ldflags="$ldflags" -tags=jsoniter .
mv alist-* dist
mv "$appName"-* dist
cd dist
cp ./alist-windows-amd64.exe ./alist-windows-amd64-upx.exe
upx -9 ./alist-windows-amd64-upx.exe
# cp ./"$appName"-windows-amd64.exe ./"$appName"-windows-amd64-upx.exe
# upx -9 ./"$appName"-windows-amd64-upx.exe
find . -type f -print0 | xargs -0 md5sum >md5.txt
cat md5.txt
}
BuildDocker() {
go build -o ./bin/alist -ldflags="$ldflags" -tags=jsoniter .
go build -o ./bin/"$appName" -ldflags="$ldflags" -tags=jsoniter .
}
PrepareBuildDockerMusl() {
mkdir -p build/musl-libs
BASE="https://musl.cc/"
FILES=(x86_64-linux-musl-cross aarch64-linux-musl-cross i486-linux-musl-cross s390x-linux-musl-cross armv6-linux-musleabihf-cross armv7l-linux-musleabihf-cross riscv64-linux-musl-cross powerpc64le-linux-musl-cross)
BASE="https://github.com/OpenListTeam/musl-compilers/releases/latest/download/"
FILES=(x86_64-linux-musl-cross aarch64-linux-musl-cross i486-linux-musl-cross armv6-linux-musleabihf-cross armv7l-linux-musleabihf-cross riscv64-linux-musl-cross powerpc64le-linux-musl-cross loongarch64-linux-musl-cross) ## Disable s390x-linux-musl-cross builds
for i in "${FILES[@]}"; do
url="${BASE}${i}.tgz"
lib_tgz="build/${i}.tgz"
curl -L -o "${lib_tgz}" "${url}"
curl -fsSL -o "${lib_tgz}" "${url}"
tar xf "${lib_tgz}" --strip-components 1 -C build/musl-libs
rm -f "${lib_tgz}"
done
@@ -109,21 +232,23 @@ BuildDockerMultiplatform() {
# run PrepareBuildDockerMusl before build
export PATH=$PATH:$PWD/build/musl-libs/bin
docker_lflags="--extldflags '-static -fpic' $ldflags"
docker_lflags="$(GetMuslStaticLdflags)"
export CGO_ENABLED=1
OS_ARCHES=(linux-amd64 linux-arm64 linux-386 linux-s390x linux-riscv64 linux-ppc64le)
CGO_ARGS=(x86_64-linux-musl-gcc aarch64-linux-musl-gcc i486-linux-musl-gcc s390x-linux-musl-gcc riscv64-linux-musl-gcc powerpc64le-linux-musl-gcc)
OS_ARCHES=(linux-amd64 linux-arm64 linux-386 linux-riscv64 linux-ppc64le linux-loong64) ## Disable linux-s390x builds
CGO_ARGS=(x86_64-linux-musl-gcc aarch64-linux-musl-gcc i486-linux-musl-gcc riscv64-linux-musl-gcc powerpc64le-linux-musl-gcc loongarch64-linux-musl-gcc) ## Disable s390x-linux-musl-gcc builds
for i in "${!OS_ARCHES[@]}"; do
os_arch=${OS_ARCHES[$i]}
cgo_cc=${CGO_ARGS[$i]}
os=${os_arch%%-*}
arch=${os_arch##*-}
build_tags=$(GetBuildTagsForTarget "$os_arch")
export GOOS=$os
export GOARCH=$arch
export CC=${cgo_cc}
echo "building for $os_arch"
go build -o build/$os/$arch/alist -ldflags="$docker_lflags" -tags=jsoniter .
CGO_LDFLAGS="-static" go build -o build/$os/$arch/"$appName" -ldflags="$docker_lflags" -tags="$build_tags" .
AssertStaticBinary "build/$os/$arch/$appName"
done
DOCKER_ARM_ARCHES=(linux-arm/v6 linux-arm/v7)
@@ -137,64 +262,222 @@ BuildDockerMultiplatform() {
export GOARM=${GO_ARM[$i]}
export CC=${cgo_cc}
echo "building for $docker_arch"
go build -o build/${docker_arch%%-*}/${docker_arch##*-}/alist -ldflags="$docker_lflags" -tags=jsoniter .
CGO_LDFLAGS="-static" go build -o build/${docker_arch%%-*}/${docker_arch##*-}/"$appName" -ldflags="$docker_lflags" -tags=jsoniter .
AssertStaticBinary "build/${docker_arch%%-*}/${docker_arch##*-}/$appName"
done
}
BuildRelease() {
rm -rf .git/
mkdir -p "build"
BuildWinArm64 ./build/alist-windows-arm64.exe
BuildWinArm64 ./build/"$appName"-windows-arm64.exe
BuildWin7 ./build/"$appName"-windows7
xgo -out "$appName" -ldflags="$ldflags" -tags=jsoniter .
# why? Because some target platforms seem to have issues with upx compression
upx -9 ./alist-linux-amd64
cp ./alist-windows-amd64.exe ./alist-windows-amd64-upx.exe
upx -9 ./alist-windows-amd64-upx.exe
mv alist-* build
# upx -9 ./"$appName"-linux-amd64
# cp ./"$appName"-windows-amd64.exe ./"$appName"-windows-amd64-upx.exe
# upx -9 ./"$appName"-windows-amd64-upx.exe
mv "$appName"-* build
# Build LoongArch with glibc (both old world abi1.0 and new world abi2.0)
# Separate from musl builds to avoid cache conflicts
BuildLoongGLIBC ./build/$appName-linux-loong64-abi1.0 abi1.0
BuildLoongGLIBC ./build/$appName-linux-loong64 abi2.0
}
BuildLoongGLIBC() {
local target_abi="$2"
local output_file="$1"
local oldWorldGoVersion="1.26.4"
local loong_tags
loong_tags=$(GetBuildTagsForTarget "linux-loong64")
if [ "$target_abi" = "abi1.0" ]; then
echo building for linux-loong64-abi1.0
else
echo building for linux-loong64-abi2.0
target_abi="abi2.0" # Default to abi2.0 if not specified
fi
# Note: No longer need global cache cleanup since ABI1.0 uses isolated cache directory
echo "Using optimized cache strategy: ABI1.0 has isolated cache, ABI2.0 uses standard cache"
if [ "$target_abi" = "abi1.0" ]; then
# Setup abi1.0 toolchain and patched Go compiler similar to cgo-action implementation
echo "Setting up Loongson old-world ABI1.0 toolchain and patched Go compiler..."
# Download and setup patched Go compiler for old-world
if ! curl -fsSL --retry 3 -H "Authorization: Bearer $GITHUB_TOKEN" \
"https://github.com/loong64-abi1-0/golang/releases/download/go${oldWorldGoVersion}/go${oldWorldGoVersion}.linux-amd64.tar.gz" \
-o go-loong64-abi1.0.tar.gz; then
echo "Error: Failed to download patched Go compiler for old-world ABI1.0"
if [ -n "$GITHUB_TOKEN" ]; then
echo "Error output from curl:"
curl -fsSL --retry 3 -H "Authorization: Bearer $GITHUB_TOKEN" \
"https://github.com/loong64-abi1-0/golang/releases/download/go${oldWorldGoVersion}/go${oldWorldGoVersion}.linux-amd64.tar.gz" \
-o go-loong64-abi1.0.tar.gz || true
fi
return 1
fi
rm -rf go-loong64-abi1.0
mkdir go-loong64-abi1.0
if ! tar -xzf go-loong64-abi1.0.tar.gz -C go-loong64-abi1.0 --strip-components=1; then
echo "Error: Failed to extract patched Go compiler"
return 1
fi
rm go-loong64-abi1.0.tar.gz
# Download and setup GCC toolchain for old-world
if ! curl -fsSL --retry 3 -H "Authorization: Bearer $GITHUB_TOKEN" \
"https://github.com/loong64/loong64-abi1.0-toolchains/releases/download/20250722/loongson-gnu-toolchain-8.3.novec-x86_64-loongarch64-linux-gnu-rc1.1.tar.xz" \
-o gcc8-loong64-abi1.0.tar.xz; then
echo "Error: Failed to download GCC toolchain for old-world ABI1.0"
if [ -n "$GITHUB_TOKEN" ]; then
echo "Error output from curl:"
curl -fsSL --retry 3 -H "Authorization: Bearer $GITHUB_TOKEN" \
"https://github.com/loong64/loong64-abi1.0-toolchains/releases/download/20250722/loongson-gnu-toolchain-8.3.novec-x86_64-loongarch64-linux-gnu-rc1.1.tar.xz" \
-o gcc8-loong64-abi1.0.tar.xz || true
fi
return 1
fi
rm -rf gcc8-loong64-abi1.0
mkdir gcc8-loong64-abi1.0
if ! tar -Jxf gcc8-loong64-abi1.0.tar.xz -C gcc8-loong64-abi1.0 --strip-components=1; then
echo "Error: Failed to extract GCC toolchain"
return 1
fi
rm gcc8-loong64-abi1.0.tar.xz
# Setup separate cache directory for ABI1.0 to avoid cache pollution
abi1_cache_dir="$(pwd)/go-loong64-abi1.0-cache"
mkdir -p "$abi1_cache_dir"
echo "Using separate cache directory for ABI1.0: $abi1_cache_dir"
# Use patched Go compiler for old-world build (critical for ABI1.0 compatibility)
echo "Building with patched Go compiler for old-world ABI1.0..."
echo "Using isolated cache directory: $abi1_cache_dir"
# Use env command to set environment variables locally without affecting global environment
if ! env GOOS=linux GOARCH=loong64 \
CC="$(pwd)/gcc8-loong64-abi1.0/bin/loongarch64-linux-gnu-gcc" \
CXX="$(pwd)/gcc8-loong64-abi1.0/bin/loongarch64-linux-gnu-g++" \
CGO_ENABLED=1 \
GOCACHE="$abi1_cache_dir" \
$(pwd)/go-loong64-abi1.0/bin/go build -a -o "$output_file" -ldflags="$ldflags" -tags="$loong_tags" .; then
echo "Error: Build failed with patched Go compiler"
echo "Attempting retry with cache cleanup..."
env GOCACHE="$abi1_cache_dir" $(pwd)/go-loong64-abi1.0/bin/go clean -cache
if ! env GOOS=linux GOARCH=loong64 \
CC="$(pwd)/gcc8-loong64-abi1.0/bin/loongarch64-linux-gnu-gcc" \
CXX="$(pwd)/gcc8-loong64-abi1.0/bin/loongarch64-linux-gnu-g++" \
CGO_ENABLED=1 \
GOCACHE="$abi1_cache_dir" \
$(pwd)/go-loong64-abi1.0/bin/go build -a -o "$output_file" -ldflags="$ldflags" -tags="$loong_tags" .; then
echo "Error: Build failed again after cache cleanup"
echo "Build environment details:"
echo "GOOS=linux"
echo "GOARCH=loong64"
echo "CC=$(pwd)/gcc8-loong64-abi1.0/bin/loongarch64-linux-gnu-gcc"
echo "CXX=$(pwd)/gcc8-loong64-abi1.0/bin/loongarch64-linux-gnu-g++"
echo "CGO_ENABLED=1"
echo "GOCACHE=$abi1_cache_dir"
echo "Go version: $($(pwd)/go-loong64-abi1.0/bin/go version)"
echo "GCC version: $($(pwd)/gcc8-loong64-abi1.0/bin/loongarch64-linux-gnu-gcc --version | head -1)"
return 1
fi
fi
else
# Setup abi2.0 toolchain for new world glibc build
echo "Setting up new-world ABI2.0 toolchain..."
if ! curl -fsSL --retry 3 -H "Authorization: Bearer $GITHUB_TOKEN" \
"https://github.com/loong64/cross-tools/releases/download/20250507/x86_64-cross-tools-loongarch64-unknown-linux-gnu-legacy.tar.xz" \
-o gcc12-loong64-abi2.0.tar.xz; then
echo "Error: Failed to download GCC toolchain for new-world ABI2.0"
if [ -n "$GITHUB_TOKEN" ]; then
echo "Error output from curl:"
curl -fsSL --retry 3 -H "Authorization: Bearer $GITHUB_TOKEN" \
"https://github.com/loong64/cross-tools/releases/download/20250507/x86_64-cross-tools-loongarch64-unknown-linux-gnu-legacy.tar.xz" \
-o gcc12-loong64-abi2.0.tar.xz || true
fi
return 1
fi
rm -rf gcc12-loong64-abi2.0
mkdir gcc12-loong64-abi2.0
if ! tar -Jxf gcc12-loong64-abi2.0.tar.xz -C gcc12-loong64-abi2.0 --strip-components=1; then
echo "Error: Failed to extract GCC toolchain"
return 1
fi
rm gcc12-loong64-abi2.0.tar.xz
export GOOS=linux
export GOARCH=loong64
export CC=$(pwd)/gcc12-loong64-abi2.0/bin/loongarch64-unknown-linux-gnu-gcc
export CXX=$(pwd)/gcc12-loong64-abi2.0/bin/loongarch64-unknown-linux-gnu-g++
export CGO_ENABLED=1
# Use standard Go compiler for new-world build
echo "Building with standard Go compiler for new-world ABI2.0..."
if ! go build -a -o "$output_file" -ldflags="$ldflags" -tags="$loong_tags" .; then
echo "Error: Build failed with standard Go compiler"
echo "Attempting retry with cache cleanup..."
go clean -cache
if ! go build -a -o "$output_file" -ldflags="$ldflags" -tags="$loong_tags" .; then
echo "Error: Build failed again after cache cleanup"
echo "Build environment details:"
echo "GOOS=$GOOS"
echo "GOARCH=$GOARCH"
echo "CC=$CC"
echo "CXX=$CXX"
echo "CGO_ENABLED=$CGO_ENABLED"
echo "Go version: $(go version)"
echo "GCC version: $($CC --version | head -1)"
return 1
fi
fi
fi
}
BuildReleaseLinuxMusl() {
rm -rf .git/
mkdir -p "build"
muslflags="--extldflags '-static -fpic' $ldflags"
BASE="https://musl.nn.ci/"
FILES=(x86_64-linux-musl-cross aarch64-linux-musl-cross mips-linux-musl-cross mips64-linux-musl-cross mips64el-linux-musl-cross mipsel-linux-musl-cross powerpc64le-linux-musl-cross s390x-linux-musl-cross)
muslflags="$(GetMuslStaticLdflags)"
BASE="https://github.com/OpenListTeam/musl-compilers/releases/latest/download/"
# Keep mips-family targets enabled; sqlite driver selection is handled by Go build tags.
FILES=(x86_64-linux-musl-cross aarch64-linux-musl-cross mips-linux-musl-cross mips64-linux-musl-cross mips64el-linux-musl-cross mipsel-linux-musl-cross powerpc64le-linux-musl-cross s390x-linux-musl-cross loongarch64-linux-musl-cross)
for i in "${FILES[@]}"; do
url="${BASE}${i}.tgz"
curl -L -o "${i}.tgz" "${url}"
curl -fsSL -o "${i}.tgz" "${url}"
sudo tar xf "${i}.tgz" --strip-components 1 -C /usr/local
rm -f "${i}.tgz"
done
OS_ARCHES=(linux-musl-amd64 linux-musl-arm64 linux-musl-mips linux-musl-mips64 linux-musl-mips64le linux-musl-mipsle linux-musl-ppc64le linux-musl-s390x)
CGO_ARGS=(x86_64-linux-musl-gcc aarch64-linux-musl-gcc mips-linux-musl-gcc mips64-linux-musl-gcc mips64el-linux-musl-gcc mipsel-linux-musl-gcc powerpc64le-linux-musl-gcc s390x-linux-musl-gcc)
OS_ARCHES=(linux-musl-amd64 linux-musl-arm64 linux-musl-mips linux-musl-mips64 linux-musl-mips64le linux-musl-mipsle linux-musl-ppc64le linux-musl-s390x linux-musl-loong64)
CGO_ARGS=(x86_64-linux-musl-gcc aarch64-linux-musl-gcc mips-linux-musl-gcc mips64-linux-musl-gcc mips64el-linux-musl-gcc mipsel-linux-musl-gcc powerpc64le-linux-musl-gcc s390x-linux-musl-gcc loongarch64-linux-musl-gcc)
for i in "${!OS_ARCHES[@]}"; do
os_arch=${OS_ARCHES[$i]}
cgo_cc=${CGO_ARGS[$i]}
build_tags=$(GetBuildTagsForTarget "$os_arch")
echo building for ${os_arch}
export GOOS=${os_arch%%-*}
export GOARCH=${os_arch##*-}
export CC=${cgo_cc}
export CGO_ENABLED=1
go build -o ./build/$appName-$os_arch -ldflags="$muslflags" -tags=jsoniter .
CGO_LDFLAGS="-static" go build -o ./build/$appName-$os_arch -ldflags="$muslflags" -tags="$build_tags" .
AssertStaticBinary "./build/$appName-$os_arch"
done
}
BuildReleaseLinuxMuslArm() {
rm -rf .git/
mkdir -p "build"
muslflags="--extldflags '-static -fpic' $ldflags"
BASE="https://musl.nn.ci/"
# FILES=(arm-linux-musleabi-cross arm-linux-musleabihf-cross armeb-linux-musleabi-cross armeb-linux-musleabihf-cross armel-linux-musleabi-cross armel-linux-musleabihf-cross armv5l-linux-musleabi-cross armv5l-linux-musleabihf-cross armv6-linux-musleabi-cross armv6-linux-musleabihf-cross armv7l-linux-musleabihf-cross armv7m-linux-musleabi-cross armv7r-linux-musleabihf-cross)
muslflags="$(GetMuslStaticLdflags)"
BASE="https://github.com/OpenListTeam/musl-compilers/releases/latest/download/"
FILES=(arm-linux-musleabi-cross arm-linux-musleabihf-cross armel-linux-musleabi-cross armel-linux-musleabihf-cross armv5l-linux-musleabi-cross armv5l-linux-musleabihf-cross armv6-linux-musleabi-cross armv6-linux-musleabihf-cross armv7l-linux-musleabihf-cross armv7m-linux-musleabi-cross armv7r-linux-musleabihf-cross)
for i in "${FILES[@]}"; do
url="${BASE}${i}.tgz"
curl -L -o "${i}.tgz" "${url}"
curl -fsSL -o "${i}.tgz" "${url}"
sudo tar xf "${i}.tgz" --strip-components 1 -C /usr/local
rm -f "${i}.tgz"
done
# OS_ARCHES=(linux-musleabi-arm linux-musleabihf-arm linux-musleabi-armeb linux-musleabihf-armeb linux-musleabi-armel linux-musleabihf-armel linux-musleabi-armv5l linux-musleabihf-armv5l linux-musleabi-armv6 linux-musleabihf-armv6 linux-musleabihf-armv7l linux-musleabi-armv7m linux-musleabihf-armv7r)
# CGO_ARGS=(arm-linux-musleabi-gcc arm-linux-musleabihf-gcc armeb-linux-musleabi-gcc armeb-linux-musleabihf-gcc armel-linux-musleabi-gcc armel-linux-musleabihf-gcc armv5l-linux-musleabi-gcc armv5l-linux-musleabihf-gcc armv6-linux-musleabi-gcc armv6-linux-musleabihf-gcc armv7l-linux-musleabihf-gcc armv7m-linux-musleabi-gcc armv7r-linux-musleabihf-gcc)
# GOARMS=('' '' '' '' '' '' '5' '5' '6' '6' '7' '7' '7')
OS_ARCHES=(linux-musleabi-arm linux-musleabihf-arm linux-musleabi-armel linux-musleabihf-armel linux-musleabi-armv5l linux-musleabihf-armv5l linux-musleabi-armv6 linux-musleabihf-armv6 linux-musleabihf-armv7l linux-musleabi-armv7m linux-musleabihf-armv7r)
CGO_ARGS=(arm-linux-musleabi-gcc arm-linux-musleabihf-gcc armel-linux-musleabi-gcc armel-linux-musleabihf-gcc armv5l-linux-musleabi-gcc armv5l-linux-musleabihf-gcc armv6-linux-musleabi-gcc armv6-linux-musleabihf-gcc armv7l-linux-musleabihf-gcc armv7m-linux-musleabi-gcc armv7r-linux-musleabihf-gcc)
GOARMS=('' '' '' '' '5' '5' '6' '6' '7' '7' '7')
@@ -208,12 +491,13 @@ BuildReleaseLinuxMuslArm() {
export CC=${cgo_cc}
export CGO_ENABLED=1
export GOARM=${arm}
go build -o ./build/$appName-$os_arch -ldflags="$muslflags" -tags=jsoniter .
CGO_LDFLAGS="-static" go build -o ./build/$appName-$os_arch -ldflags="$muslflags" -tags=jsoniter .
AssertStaticBinary "./build/$appName-$os_arch"
done
}
BuildReleaseAndroid() {
rm -rf .git/
mkdir -p "build"
wget https://dl.google.com/android/repository/android-ndk-r26b-linux.zip
unzip android-ndk-r26b-linux.zip
@@ -234,17 +518,34 @@ BuildReleaseAndroid() {
}
BuildReleaseFreeBSD() {
rm -rf .git/
mkdir -p "build/freebsd"
# Get latest FreeBSD 14.x release version from GitHub
freebsd_version=$(eval "curl -fsSL --max-time 2 $githubAuthArgs \"https://api.github.com/repos/freebsd/freebsd-src/tags\"" | \
jq -r '.[].name' | \
grep '^release/14\.' | \
grep -v -- '-p[0-9]*$' | \
sort -V | \
tail -1 | \
sed 's/release\///' | \
sed 's/\.0$//')
if [ -z "$freebsd_version" ]; then
echo "Failed to get FreeBSD version, falling back to 14.4"
freebsd_version="14.4"
fi
echo "Using FreeBSD version: $freebsd_version"
OS_ARCHES=(amd64 arm64 i386)
GO_ARCHES=(amd64 arm64 386)
CGO_ARGS=(x86_64-unknown-freebsd14.1 aarch64-unknown-freebsd14.1 i386-unknown-freebsd14.1)
CGO_ARGS=(x86_64-unknown-freebsd${freebsd_version} aarch64-unknown-freebsd${freebsd_version} i386-unknown-freebsd${freebsd_version})
for i in "${!OS_ARCHES[@]}"; do
os_arch=${OS_ARCHES[$i]}
cgo_cc="clang --target=${CGO_ARGS[$i]} --sysroot=/opt/freebsd/${os_arch}"
echo building for freebsd-${os_arch}
sudo mkdir -p "/opt/freebsd/${os_arch}"
wget -q https://download.freebsd.org/releases/${os_arch}/14.1-RELEASE/base.txz
wget -q https://download.freebsd.org/releases/${os_arch}/${freebsd_version}-RELEASE/base.txz
sudo tar -xf ./base.txz -C /opt/freebsd/${os_arch}
rm base.txz
export GOOS=freebsd
@@ -258,79 +559,176 @@ BuildReleaseFreeBSD() {
MakeRelease() {
cd build
if [ -d compress ]; then
rm -rv compress
fi
mkdir compress
# Add -lite suffix if useLite is true
liteSuffix=""
if [ "$useLite" = true ]; then
liteSuffix="-lite"
fi
for i in $(find . -type f -name "$appName-linux-*"); do
cp "$i" alist
tar -czvf compress/"$i".tar.gz alist
rm -f alist
cp "$i" "$appName"
tar -czvf compress/"$i$liteSuffix".tar.gz "$appName"
rm -f "$appName"
done
for i in $(find . -type f -name "$appName-android-*"); do
cp "$i" alist
tar -czvf compress/"$i".tar.gz alist
rm -f alist
cp "$i" "$appName"
tar -czvf compress/"$i$liteSuffix".tar.gz "$appName"
rm -f "$appName"
done
for i in $(find . -type f -name "$appName-darwin-*"); do
cp "$i" alist
tar -czvf compress/"$i".tar.gz alist
rm -f alist
cp "$i" "$appName"
tar -czvf compress/"$i$liteSuffix".tar.gz "$appName"
rm -f "$appName"
done
for i in $(find . -type f -name "$appName-freebsd-*"); do
cp "$i" alist
tar -czvf compress/"$i".tar.gz alist
rm -f alist
cp "$i" "$appName"
tar -czvf compress/"$i$liteSuffix".tar.gz "$appName"
rm -f "$appName"
done
for i in $(find . -type f -name "$appName-windows-*"); do
cp "$i" alist.exe
zip compress/$(echo $i | sed 's/\.[^.]*$//').zip alist.exe
rm -f alist.exe
for i in $(find . -type f \( -name "$appName-windows-*" -o -name "$appName-windows7-*" \)); do
cp "$i" "$appName".exe
zip compress/$(echo $i | sed 's/\.[^.]*$//')$liteSuffix.zip "$appName".exe
rm -f "$appName".exe
done
cd compress
find . -type f -print0 | xargs -0 md5sum >"$1"
cat "$1"
# Handle MD5 filename - add -lite suffix only if not already present
md5FileName="$1"
if [ "$useLite" = true ] && [[ "$1" != *"-lite.txt" ]]; then
md5FileName=$(echo "$1" | sed 's/\.txt$/-lite.txt/')
fi
find . -type f -print0 | xargs -0 md5sum >"$md5FileName"
cat "$md5FileName"
cd ../..
}
if [ "$1" = "dev" ]; then
FetchWebDev
if [ "$2" = "docker" ]; then
# Parse parameters to handle lite parameter position flexibility
buildType=""
dockerType=""
otherParam=""
for arg in "$@"; do
case $arg in
dev|beta|release|zip|prepare)
if [ -z "$buildType" ]; then
buildType="$arg"
fi
;;
docker|docker-multiplatform|linux_musl_arm|linux_musl|android|freebsd|web)
if [ -z "$dockerType" ]; then
dockerType="$arg"
fi
;;
lite)
# lite parameter is already handled above
;;
*)
if [ -z "$otherParam" ]; then
otherParam="$arg"
fi
;;
esac
done
if [ "$buildType" = "dev" ]; then
FetchWebRolling
if [ "$dockerType" = "docker" ]; then
BuildDocker
elif [ "$2" = "docker-multiplatform" ]; then
elif [ "$dockerType" = "docker-multiplatform" ]; then
BuildDockerMultiplatform
elif [ "$2" = "web" ]; then
elif [ "$dockerType" = "web" ]; then
echo "web only"
else
BuildDev
fi
elif [ "$1" = "release" ]; then
FetchWebRelease
if [ "$2" = "docker" ]; then
elif [ "$buildType" = "release" -o "$buildType" = "beta" ]; then
if [ "$buildType" = "beta" ]; then
FetchWebRolling
else
FetchWebRelease
fi
if [ "$dockerType" = "docker" ]; then
BuildDocker
elif [ "$2" = "docker-multiplatform" ]; then
elif [ "$dockerType" = "docker-multiplatform" ]; then
BuildDockerMultiplatform
elif [ "$2" = "linux_musl_arm" ]; then
elif [ "$dockerType" = "linux_musl_arm" ]; then
BuildReleaseLinuxMuslArm
MakeRelease "md5-linux-musl-arm.txt"
elif [ "$2" = "linux_musl" ]; then
if [ "$useLite" = true ]; then
MakeRelease "md5-linux-musl-arm-lite.txt"
else
MakeRelease "md5-linux-musl-arm.txt"
fi
elif [ "$dockerType" = "linux_musl" ]; then
BuildReleaseLinuxMusl
MakeRelease "md5-linux-musl.txt"
elif [ "$2" = "android" ]; then
if [ "$useLite" = true ]; then
MakeRelease "md5-linux-musl-lite.txt"
else
MakeRelease "md5-linux-musl.txt"
fi
elif [ "$dockerType" = "android" ]; then
BuildReleaseAndroid
MakeRelease "md5-android.txt"
elif [ "$2" = "freebsd" ]; then
if [ "$useLite" = true ]; then
MakeRelease "md5-android-lite.txt"
else
MakeRelease "md5-android.txt"
fi
elif [ "$dockerType" = "freebsd" ]; then
BuildReleaseFreeBSD
MakeRelease "md5-freebsd.txt"
elif [ "$2" = "web" ]; then
if [ "$useLite" = true ]; then
MakeRelease "md5-freebsd-lite.txt"
else
MakeRelease "md5-freebsd.txt"
fi
elif [ "$dockerType" = "web" ]; then
echo "web only"
else
BuildRelease
MakeRelease "md5.txt"
if [ "$useLite" = true ]; then
MakeRelease "md5-lite.txt"
else
MakeRelease "md5.txt"
fi
fi
elif [ "$1" = "prepare" ]; then
if [ "$2" = "docker-multiplatform" ]; then
elif [ "$buildType" = "prepare" ]; then
if [ "$dockerType" = "docker-multiplatform" ]; then
PrepareBuildDockerMusl
fi
elif [ "$1" = "zip" ]; then
MakeRelease "$2".txt
elif [ "$buildType" = "zip" ]; then
if [ -n "$otherParam" ]; then
if [ "$useLite" = true ]; then
MakeRelease "$otherParam-lite.txt"
else
MakeRelease "$otherParam.txt"
fi
elif [ -n "$dockerType" ]; then
if [ "$useLite" = true ]; then
MakeRelease "$dockerType-lite.txt"
else
MakeRelease "$dockerType.txt"
fi
else
if [ "$useLite" = true ]; then
MakeRelease "md5-lite.txt"
else
MakeRelease "md5.txt"
fi
fi
else
echo -e "Parameter error"
echo -e "Usage: $0 {dev|beta|release|zip|prepare} [docker|docker-multiplatform|linux_musl_arm|linux_musl|android|freebsd|web] [lite] [other_params]"
echo -e "Examples:"
echo -e " $0 dev"
echo -e " $0 dev lite"
echo -e " $0 dev docker"
echo -e " $0 dev docker lite"
echo -e " $0 release"
echo -e " $0 release lite"
echo -e " $0 release docker lite"
echo -e " $0 release linux_musl"
fi
+29 -22
View File
@@ -4,11 +4,14 @@ Copyright © 2022 NAME HERE <EMAIL ADDRESS>
package cmd
import (
"github.com/alist-org/alist/v3/internal/conf"
"github.com/alist-org/alist/v3/internal/op"
"github.com/alist-org/alist/v3/internal/setting"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/alist-org/alist/v3/pkg/utils/random"
"fmt"
"github.com/OpenListTeam/OpenList/v4/internal/bootstrap"
"github.com/OpenListTeam/OpenList/v4/internal/conf"
"github.com/OpenListTeam/OpenList/v4/internal/op"
"github.com/OpenListTeam/OpenList/v4/internal/setting"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
"github.com/OpenListTeam/OpenList/v4/pkg/utils/random"
"github.com/spf13/cobra"
)
@@ -18,16 +21,17 @@ var AdminCmd = &cobra.Command{
Aliases: []string{"password"},
Short: "Show admin user's info and some operations about admin user's password",
Run: func(cmd *cobra.Command, args []string) {
Init()
defer Release()
bootstrap.Init()
defer bootstrap.Release()
admin, err := op.GetAdmin()
if err != nil {
utils.Log.Errorf("failed get admin user: %+v", err)
} else {
utils.Log.Infof("Admin user's username: %s", admin.Username)
utils.Log.Infof("The password can only be output at the first startup, and then stored as a hash value, which cannot be reversed")
utils.Log.Infof("You can reset the password with a random string by running [alist admin random]")
utils.Log.Infof("You can also set a new password by running [alist admin set NEW_PASSWORD]")
utils.Log.Infof("get admin user from CLI")
fmt.Println("Admin user's username:", admin.Username)
fmt.Println("The password can only be output at the first startup, and then stored as a hash value, which cannot be reversed")
fmt.Println("You can reset the password with a random string by running [openlist admin random]")
fmt.Println("You can also set a new password by running [openlist admin set NEW_PASSWORD]")
}
},
}
@@ -36,6 +40,7 @@ var RandomPasswordCmd = &cobra.Command{
Use: "random",
Short: "Reset admin user's password to a random string",
Run: func(cmd *cobra.Command, args []string) {
utils.Log.Infof("reset admin user's password to a random string from CLI")
newPwd := random.String(8)
setAdminPassword(newPwd)
},
@@ -44,12 +49,12 @@ var RandomPasswordCmd = &cobra.Command{
var SetPasswordCmd = &cobra.Command{
Use: "set",
Short: "Set admin user's password",
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
utils.Log.Errorf("Please enter the new password")
return
return fmt.Errorf("Please enter the new password")
}
setAdminPassword(args[0])
return nil
},
}
@@ -57,16 +62,17 @@ var ShowTokenCmd = &cobra.Command{
Use: "token",
Short: "Show admin token",
Run: func(cmd *cobra.Command, args []string) {
Init()
defer Release()
bootstrap.Init()
defer bootstrap.Release()
token := setting.GetStr(conf.Token)
utils.Log.Infof("Admin token: %s", token)
utils.Log.Infof("show admin token from CLI")
fmt.Println("Admin token:", token)
},
}
func setAdminPassword(pwd string) {
Init()
defer Release()
bootstrap.Init()
defer bootstrap.Release()
admin, err := op.GetAdmin()
if err != nil {
utils.Log.Errorf("failed get admin user: %+v", err)
@@ -77,9 +83,10 @@ func setAdminPassword(pwd string) {
utils.Log.Errorf("failed update admin user: %+v", err)
return
}
utils.Log.Infof("admin user has been updated:")
utils.Log.Infof("username: %s", admin.Username)
utils.Log.Infof("password: %s", pwd)
utils.Log.Infof("admin user has been update from CLI")
fmt.Println("admin user has been updated:")
fmt.Println("username:", admin.Username)
fmt.Println("password:", pwd)
DelAdminCacheOnline()
}
+9 -5
View File
@@ -4,8 +4,11 @@ Copyright © 2022 NAME HERE <EMAIL ADDRESS>
package cmd
import (
"github.com/alist-org/alist/v3/internal/op"
"github.com/alist-org/alist/v3/pkg/utils"
"fmt"
"github.com/OpenListTeam/OpenList/v4/internal/bootstrap"
"github.com/OpenListTeam/OpenList/v4/internal/op"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
"github.com/spf13/cobra"
)
@@ -14,8 +17,8 @@ var Cancel2FACmd = &cobra.Command{
Use: "cancel2fa",
Short: "Delete 2FA of admin user",
Run: func(cmd *cobra.Command, args []string) {
Init()
defer Release()
bootstrap.Init()
defer bootstrap.Release()
admin, err := op.GetAdmin()
if err != nil {
utils.Log.Errorf("failed to get admin user: %+v", err)
@@ -24,7 +27,8 @@ var Cancel2FACmd = &cobra.Command{
if err != nil {
utils.Log.Errorf("failed to cancel 2FA: %+v", err)
} else {
utils.Log.Info("2FA canceled")
utils.Log.Infof("2FA is canceled from CLI")
fmt.Println("2FA canceled")
DelAdminCacheOnline()
}
}
+4 -10
View File
@@ -5,23 +5,17 @@ import (
"path/filepath"
"strconv"
"github.com/alist-org/alist/v3/internal/bootstrap"
"github.com/alist-org/alist/v3/internal/bootstrap/data"
"github.com/alist-org/alist/v3/internal/db"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/OpenListTeam/OpenList/v4/internal/bootstrap"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
log "github.com/sirupsen/logrus"
)
func Init() {
bootstrap.InitConfig()
bootstrap.Log()
bootstrap.InitDB()
data.InitData()
bootstrap.InitIndex()
bootstrap.Init()
}
func Release() {
db.Close()
bootstrap.Release()
}
var pid = -1
+309
View File
@@ -0,0 +1,309 @@
package cmd
import (
"io"
"os"
"path"
"path/filepath"
"strings"
rcCrypt "github.com/rclone/rclone/backend/crypt"
"github.com/rclone/rclone/fs/config/configmap"
"github.com/rclone/rclone/fs/config/obscure"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// encryption and decryption command format for Crypt driver
type options struct {
op string //decrypt or encrypt
src string //source dir or file
dst string //out destination
pwd string //de/encrypt password
salt string
filenameEncryption string //reference drivers\crypt\meta.go Addition
dirnameEncryption string
filenameEncode string
suffix string
}
var opt options
// CryptCmd represents the crypt command
var CryptCmd = &cobra.Command{
Use: "crypt",
Short: "Encrypt or decrypt local file or dir",
Example: `openlist crypt -s ./src/encrypt/ --op=de --pwd=123456 --salt=345678`,
Run: func(cmd *cobra.Command, args []string) {
opt.validate()
opt.cryptFileDir()
},
}
func init() {
RootCmd.AddCommand(CryptCmd)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// versionCmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
CryptCmd.Flags().StringVarP(&opt.src, "src", "s", "", "src file or dir to encrypt/decrypt")
CryptCmd.Flags().StringVarP(&opt.dst, "dst", "d", "", "dst dir to output,if not set,output to src dir")
CryptCmd.Flags().StringVar(&opt.op, "op", "", "de or en which stands for decrypt or encrypt")
CryptCmd.Flags().StringVar(&opt.pwd, "pwd", "", "password used to encrypt/decrypt,if not contain ___Obfuscated___ prefix,will be obfuscated before used")
CryptCmd.Flags().StringVar(&opt.salt, "salt", "", "salt used to encrypt/decrypt,if not contain ___Obfuscated___ prefix,will be obfuscated before used")
CryptCmd.Flags().StringVar(&opt.filenameEncryption, "filename-encrypt", "off", "filename encryption mode: off,standard,obfuscate")
CryptCmd.Flags().StringVar(&opt.dirnameEncryption, "dirname-encrypt", "false", "is dirname encryption enabled:true,false")
CryptCmd.Flags().StringVar(&opt.filenameEncode, "filename-encode", "base64", "filename encoding mode: base64,base32,base32768")
CryptCmd.Flags().StringVar(&opt.suffix, "suffix", ".bin", "suffix for encrypted file,default is .bin")
}
func (o *options) validate() {
if o.src == "" {
log.Fatal("src can not be empty")
}
if o.op != "encrypt" && o.op != "decrypt" && o.op != "en" && o.op != "de" {
log.Fatal("op must be encrypt or decrypt")
}
if o.filenameEncryption != "off" && o.filenameEncryption != "standard" && o.filenameEncryption != "obfuscate" {
log.Fatal("filename_encryption must be off,standard,obfuscate")
}
if o.filenameEncode != "base64" && o.filenameEncode != "base32" && o.filenameEncode != "base32768" {
log.Fatal("filename_encode must be base64,base32,base32768")
}
}
func (o *options) cryptFileDir() {
src, _ := filepath.Abs(o.src)
log.Infof("src abs is %v", src)
fileInfo, err := os.Stat(src)
if err != nil {
log.Fatalf("reading file/dir %v failed,err:%v", src, err)
}
pwd := updateObfusParm(o.pwd)
salt := updateObfusParm(o.salt)
//create cipher
config := configmap.Simple{
"password": pwd,
"password2": salt,
"filename_encryption": o.filenameEncryption,
"directory_name_encryption": o.dirnameEncryption,
"filename_encoding": o.filenameEncode,
"suffix": o.suffix,
"pass_bad_blocks": "",
}
log.Infof("config:%v", config)
cipher, err := rcCrypt.NewCipher(config)
if err != nil {
log.Fatalf("create cipher failed,err:%v", err)
}
dst := ""
//check and create dst dir
if o.dst != "" {
dst, _ = filepath.Abs(o.dst)
checkCreateDir(dst)
}
// src is file
if !fileInfo.IsDir() { //file
if dst == "" {
dst = filepath.Dir(src)
}
o.cryptFile(cipher, src, dst)
return
}
// src is dir
if dst == "" {
//if src is dir and not set dst dir ,create ${src}_crypt dir as dst dir
dst = path.Join(filepath.Dir(src), fileInfo.Name()+"_crypt")
}
log.Infof("dst : %v", dst)
dirnameMap := make(map[string]string)
pathSeparator := string(os.PathSeparator)
filepath.Walk(src, func(p string, info os.FileInfo, err error) error {
if err != nil {
log.Errorf("get file %v info failed, err:%v", p, err)
return err
}
if p == src {
return nil
}
log.Infof("current path %v", p)
// relative path
rp := strings.ReplaceAll(p, src, "")
log.Infof("relative path %v", rp)
rpds := strings.Split(rp, pathSeparator)
if info.IsDir() {
// absolute dst dir for current path
dd := ""
if o.dirnameEncryption == "true" {
if o.op == "encrypt" || o.op == "en" {
for i := range rpds {
oname := rpds[i]
if _, ok := dirnameMap[rpds[i]]; ok {
rpds[i] = dirnameMap[rpds[i]]
} else {
rpds[i] = cipher.EncryptDirName(rpds[i])
dirnameMap[oname] = rpds[i]
}
}
dd = path.Join(dst, strings.Join(rpds, pathSeparator))
} else {
for i := range rpds {
oname := rpds[i]
if _, ok := dirnameMap[rpds[i]]; ok {
rpds[i] = dirnameMap[rpds[i]]
} else {
dnn, err := cipher.DecryptDirName(rpds[i])
if err != nil {
log.Fatalf("decrypt dir name %v failed,err:%v", rpds[i], err)
}
rpds[i] = dnn
dirnameMap[oname] = dnn
}
}
dd = path.Join(dst, strings.Join(rpds, pathSeparator))
}
} else {
dd = path.Join(dst, rp)
}
log.Infof("create output dir %v", dd)
checkCreateDir(dd)
return nil
}
// file dst dir
fdd := dst
if o.dirnameEncryption == "true" {
for i := range rpds {
if i == len(rpds)-1 {
break
}
fdd = path.Join(fdd, dirnameMap[rpds[i]])
}
} else {
fdd = path.Join(fdd, strings.Join(rpds[:len(rpds)-1], pathSeparator))
}
log.Infof("file output dir %v", fdd)
o.cryptFile(cipher, p, fdd)
return nil
})
}
func (o *options) cryptFile(cipher *rcCrypt.Cipher, src string, dst string) {
fileInfo, err := os.Stat(src)
if err != nil {
log.Fatalf("get file %v info failed,err:%v", src, err)
}
fd, err := os.OpenFile(src, os.O_RDWR, 0666)
if err != nil {
log.Fatalf("open file %v failed,err:%v", src, err)
}
defer fd.Close()
var cryptSrcReader io.Reader
var outFile string
if o.op == "encrypt" || o.op == "en" {
filename := fileInfo.Name()
if o.filenameEncryption != "off" {
filename = cipher.EncryptFileName(fileInfo.Name())
log.Infof("encrypt file name %v to %v", fileInfo.Name(), filename)
} else {
filename = fileInfo.Name() + o.suffix
}
cryptSrcReader, err = cipher.EncryptData(fd)
if err != nil {
log.Fatalf("encrypt file %v failed,err:%v", src, err)
}
outFile = path.Join(dst, filename)
} else {
filename := fileInfo.Name()
if o.filenameEncryption != "off" {
filename, err = cipher.DecryptFileName(filename)
if err != nil {
log.Fatalf("decrypt file name %v failed,err:%v", src, err)
}
log.Infof("decrypt file name %v to %v, ", fileInfo.Name(), filename)
} else {
filename = strings.TrimSuffix(filename, o.suffix)
}
cryptSrcReader, err = cipher.DecryptData(fd)
if err != nil {
log.Fatalf("decrypt file %v failed,err:%v", src, err)
}
outFile = path.Join(dst, filename)
}
//write new file
wr, err := os.OpenFile(outFile, os.O_CREATE|os.O_WRONLY, 0755)
if err != nil {
log.Fatalf("create file %v failed,err:%v", outFile, err)
}
defer wr.Close()
_, err = io.Copy(wr, cryptSrcReader)
if err != nil {
log.Fatalf("write file %v failed,err:%v", outFile, err)
}
}
// check dir exist ,if not ,create
func checkCreateDir(dir string) {
_, err := os.Stat(dir)
if os.IsNotExist(err) {
err := os.MkdirAll(dir, 0755)
if err != nil {
log.Fatalf("create dir %v failed,err:%v", dir, err)
}
return
} else if err != nil {
log.Fatalf("read dir %v err: %v", dir, err)
}
}
func updateObfusParm(str string) string {
obfuscatedPrefix := "___Obfuscated___"
if !strings.HasPrefix(str, obfuscatedPrefix) {
str, err := obscure.Obscure(str)
if err != nil {
log.Fatalf("update obfuscated parameter failed,err:%v", str)
}
} else {
str, _ = strings.CutPrefix(str, obfuscatedPrefix)
}
return str
}
+1
View File
@@ -2,6 +2,7 @@ package flags
var (
DataDir string
ConfigPath string
Debug bool
NoPrefix bool
Dev bool
+55
View File
@@ -0,0 +1,55 @@
package cmd
import (
"os"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// KillCmd represents the kill command
var KillCmd = &cobra.Command{
Use: "kill",
Short: "Force kill openlist server process by daemon/pid file",
Run: func(cmd *cobra.Command, args []string) {
kill()
},
}
func kill() {
initDaemon()
if pid == -1 {
log.Info("Seems not have been started. Try use `openlist start` to start server.")
return
}
process, err := os.FindProcess(pid)
if err != nil {
log.Errorf("failed to find process by pid: %d, reason: %v", pid, process)
return
}
err = process.Kill()
if err != nil {
log.Errorf("failed to kill process %d: %v", pid, err)
} else {
log.Info("killed process: ", pid)
}
err = os.Remove(pidFile)
if err != nil {
log.Errorf("failed to remove pid file")
}
pid = -1
}
func init() {
RootCmd.AddCommand(KillCmd)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// stopCmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// stopCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
+34 -9
View File
@@ -8,14 +8,14 @@ import (
"fmt"
"io"
"os"
"reflect"
"strings"
_ "github.com/alist-org/alist/v3/drivers"
"github.com/alist-org/alist/v3/internal/bootstrap/data"
"github.com/alist-org/alist/v3/internal/conf"
"github.com/alist-org/alist/v3/internal/op"
"github.com/alist-org/alist/v3/pkg/utils"
_ "github.com/OpenListTeam/OpenList/v4/drivers"
"github.com/OpenListTeam/OpenList/v4/internal/bootstrap"
"github.com/OpenListTeam/OpenList/v4/internal/bootstrap/data"
"github.com/OpenListTeam/OpenList/v4/internal/conf"
"github.com/OpenListTeam/OpenList/v4/internal/op"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -24,6 +24,8 @@ type KV[V any] map[string]V
type Drivers KV[KV[interface{}]]
var frontendPath string
func firstUpper(s string) string {
if s == "" {
return ""
@@ -38,7 +40,7 @@ func convert(s string) string {
}
func writeFile(name string, data interface{}) {
f, err := os.Open(fmt.Sprintf("../alist-web/src/lang/en/%s.json", name))
f, err := os.Open(fmt.Sprintf("%s/src/lang/en/%s.json", frontendPath, name))
if err != nil {
log.Errorf("failed to open %s.json: %+v", name, err)
return
@@ -66,15 +68,33 @@ func writeFile(name string, data interface{}) {
log.Errorf("failed to unmarshal json: %+v", err)
return
}
if reflect.DeepEqual(oldData, newData) {
if mergeJson(newData, oldData) {
log.Infof("%s.json no changed, skip", name)
} else {
log.Infof("%s.json changed, update file", name)
//log.Infof("old: %+v\nnew:%+v", oldData, data)
utils.WriteJsonToFile(fmt.Sprintf("lang/%s.json", name), newData, true)
utils.WriteJsonToFile(fmt.Sprintf("lang/%s.json", name), oldData, true)
}
}
func mergeJson(source, target map[string]interface{}) bool {
equal := true
for k, v := range source {
tgtV, tgtOk := target[k]
if !tgtOk {
equal = false
target[k] = v
} else {
srcMap, srcIsMap := v.(map[string]interface{})
tgtMap, tgtIsMap := tgtV.(map[string]interface{})
if srcIsMap && tgtIsMap {
equal = mergeJson(srcMap, tgtMap) && equal
}
}
}
return equal
}
func generateDriversJson() {
drivers := make(Drivers)
drivers["drivers"] = make(KV[interface{}])
@@ -137,6 +157,8 @@ var LangCmd = &cobra.Command{
Use: "lang",
Short: "Generate language json file",
Run: func(cmd *cobra.Command, args []string) {
frontendPath, _ = cmd.Flags().GetString("frontend-path")
bootstrap.InitConfig()
err := os.MkdirAll("lang", 0777)
if err != nil {
utils.Log.Fatalf("failed create folder: %s", err.Error())
@@ -149,6 +171,9 @@ var LangCmd = &cobra.Command{
func init() {
RootCmd.AddCommand(LangCmd)
// Add frontend-path flag
LangCmd.Flags().String("frontend-path", "../OpenList-Frontend", "Path to the frontend project directory")
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
+1 -1
View File
@@ -10,7 +10,7 @@ import (
// RestartCmd represents the restart command
var RestartCmd = &cobra.Command{
Use: "restart",
Short: "Restart alist server by daemon/pid file",
Short: "Restart openlist server by daemon/pid file",
Run: func(cmd *cobra.Command, args []string) {
stop()
start()
+9 -7
View File
@@ -4,18 +4,19 @@ import (
"fmt"
"os"
"github.com/alist-org/alist/v3/cmd/flags"
_ "github.com/alist-org/alist/v3/drivers"
_ "github.com/alist-org/alist/v3/internal/offline_download"
"github.com/OpenListTeam/OpenList/v4/cmd/flags"
_ "github.com/OpenListTeam/OpenList/v4/drivers"
_ "github.com/OpenListTeam/OpenList/v4/internal/archive"
_ "github.com/OpenListTeam/OpenList/v4/internal/offline_download"
"github.com/spf13/cobra"
)
var RootCmd = &cobra.Command{
Use: "alist",
Use: "openlist",
Short: "A file list program that supports multiple storage.",
Long: `A file list program that supports multiple storage,
built with love by Xhofe and friends in Go/Solid.js.
Complete documentation is available at https://alist.nn.ci/`,
built with love by OpenListTeam.
Complete documentation is available at https://doc.oplist.org/`,
}
func Execute() {
@@ -26,7 +27,8 @@ func Execute() {
}
func init() {
RootCmd.PersistentFlags().StringVar(&flags.DataDir, "data", "data", "data folder")
RootCmd.PersistentFlags().StringVar(&flags.DataDir, "data", "data", "data directory (relative paths are resolved against the current working directory)")
RootCmd.PersistentFlags().StringVar(&flags.ConfigPath, "config", "", "path to config.json (relative to current working directory; defaults to [data directory]/config.json, where [data directory] is set by --data)")
RootCmd.PersistentFlags().BoolVar(&flags.Debug, "debug", false, "start with debug mode")
RootCmd.PersistentFlags().BoolVar(&flags.NoPrefix, "no-prefix", false, "disable env prefix")
RootCmd.PersistentFlags().BoolVar(&flags.Dev, "dev", false, "start with dev mode")
+7 -132
View File
@@ -1,25 +1,12 @@
package cmd
import (
"context"
"errors"
"fmt"
"net"
"net/http"
"os"
"os/signal"
"strconv"
"sync"
"syscall"
"time"
"github.com/alist-org/alist/v3/cmd/flags"
"github.com/alist-org/alist/v3/internal/bootstrap"
"github.com/alist-org/alist/v3/internal/conf"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/alist-org/alist/v3/server"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
"github.com/OpenListTeam/OpenList/v4/internal/bootstrap"
"github.com/spf13/cobra"
)
@@ -30,88 +17,9 @@ var ServerCmd = &cobra.Command{
Long: `Start the server at the specified address
the address is defined in config file`,
Run: func(cmd *cobra.Command, args []string) {
Init()
if conf.Conf.DelayedStart != 0 {
utils.Log.Infof("delayed start for %d seconds", conf.Conf.DelayedStart)
time.Sleep(time.Duration(conf.Conf.DelayedStart) * time.Second)
}
bootstrap.InitOfflineDownloadTools()
bootstrap.LoadStorages()
bootstrap.InitTaskManager()
if !flags.Debug && !flags.Dev {
gin.SetMode(gin.ReleaseMode)
}
r := gin.New()
r.Use(gin.LoggerWithWriter(log.StandardLogger().Out), gin.RecoveryWithWriter(log.StandardLogger().Out))
server.Init(r)
var httpSrv, httpsSrv, unixSrv *http.Server
if conf.Conf.Scheme.HttpPort != -1 {
httpBase := fmt.Sprintf("%s:%d", conf.Conf.Scheme.Address, conf.Conf.Scheme.HttpPort)
utils.Log.Infof("start HTTP server @ %s", httpBase)
httpSrv = &http.Server{Addr: httpBase, Handler: r}
go func() {
err := httpSrv.ListenAndServe()
if err != nil && !errors.Is(err, http.ErrServerClosed) {
utils.Log.Fatalf("failed to start http: %s", err.Error())
}
}()
}
if conf.Conf.Scheme.HttpsPort != -1 {
httpsBase := fmt.Sprintf("%s:%d", conf.Conf.Scheme.Address, conf.Conf.Scheme.HttpsPort)
utils.Log.Infof("start HTTPS server @ %s", httpsBase)
httpsSrv = &http.Server{Addr: httpsBase, Handler: r}
go func() {
err := httpsSrv.ListenAndServeTLS(conf.Conf.Scheme.CertFile, conf.Conf.Scheme.KeyFile)
if err != nil && !errors.Is(err, http.ErrServerClosed) {
utils.Log.Fatalf("failed to start https: %s", err.Error())
}
}()
}
if conf.Conf.Scheme.UnixFile != "" {
utils.Log.Infof("start unix server @ %s", conf.Conf.Scheme.UnixFile)
unixSrv = &http.Server{Handler: r}
go func() {
listener, err := net.Listen("unix", conf.Conf.Scheme.UnixFile)
if err != nil {
utils.Log.Fatalf("failed to listen unix: %+v", err)
}
// set socket file permission
mode, err := strconv.ParseUint(conf.Conf.Scheme.UnixFilePerm, 8, 32)
if err != nil {
utils.Log.Errorf("failed to parse socket file permission: %+v", err)
} else {
err = os.Chmod(conf.Conf.Scheme.UnixFile, os.FileMode(mode))
if err != nil {
utils.Log.Errorf("failed to chmod socket file: %+v", err)
}
}
err = unixSrv.Serve(listener)
if err != nil && !errors.Is(err, http.ErrServerClosed) {
utils.Log.Fatalf("failed to start unix: %s", err.Error())
}
}()
}
if conf.Conf.S3.Port != -1 && conf.Conf.S3.Enable {
s3r := gin.New()
s3r.Use(gin.LoggerWithWriter(log.StandardLogger().Out), gin.RecoveryWithWriter(log.StandardLogger().Out))
server.InitS3(s3r)
s3Base := fmt.Sprintf("%s:%d", conf.Conf.Scheme.Address, conf.Conf.S3.Port)
utils.Log.Infof("start S3 server @ %s", s3Base)
go func() {
var err error
if conf.Conf.S3.SSL {
httpsSrv = &http.Server{Addr: s3Base, Handler: s3r}
err = httpsSrv.ListenAndServeTLS(conf.Conf.Scheme.CertFile, conf.Conf.Scheme.KeyFile)
}
if !conf.Conf.S3.SSL {
httpSrv = &http.Server{Addr: s3Base, Handler: s3r}
err = httpSrv.ListenAndServe()
}
if err != nil && !errors.Is(err, http.ErrServerClosed) {
utils.Log.Fatalf("failed to start s3 server: %s", err.Error())
}
}()
}
bootstrap.Init()
defer bootstrap.Release()
bootstrap.Start()
// Wait for interrupt signal to gracefully shutdown the server with
// a timeout of 1 second.
quit := make(chan os.Signal, 1)
@@ -120,40 +28,7 @@ the address is defined in config file`,
// kill -9 is syscall. SIGKILL but can"t be catch, so don't need add it
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
utils.Log.Println("Shutdown server...")
Release()
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
var wg sync.WaitGroup
if conf.Conf.Scheme.HttpPort != -1 {
wg.Add(1)
go func() {
defer wg.Done()
if err := httpSrv.Shutdown(ctx); err != nil {
utils.Log.Fatal("HTTP server shutdown err: ", err)
}
}()
}
if conf.Conf.Scheme.HttpsPort != -1 {
wg.Add(1)
go func() {
defer wg.Done()
if err := httpsSrv.Shutdown(ctx); err != nil {
utils.Log.Fatal("HTTPS server shutdown err: ", err)
}
}()
}
if conf.Conf.Scheme.UnixFile != "" {
wg.Add(1)
go func() {
defer wg.Done()
if err := unixSrv.Shutdown(ctx); err != nil {
utils.Log.Fatal("Unix server shutdown err: ", err)
}
}()
}
wg.Wait()
utils.Log.Println("Server exit")
bootstrap.Shutdown(1 * time.Second)
},
}
@@ -171,8 +46,8 @@ func init() {
// serverCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
// OutAlistInit 暴露用于外部启动server的函数
func OutAlistInit() {
// OutOpenListInit 暴露用于外部启动server的函数
func OutOpenListInit() {
var (
cmd *cobra.Command
args []string
+20 -10
View File
@@ -8,6 +8,7 @@ import (
"os/exec"
"path/filepath"
"strconv"
"strings"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -16,7 +17,7 @@ import (
// StartCmd represents the start command
var StartCmd = &cobra.Command{
Use: "start",
Short: "Silent start alist server with `--force-bin-dir`",
Short: "Silent start openlist server with `--force-bin-dir`",
Run: func(cmd *cobra.Command, args []string) {
start()
},
@@ -27,18 +28,27 @@ func start() {
if pid != -1 {
_, err := os.FindProcess(pid)
if err == nil {
log.Info("alist already started, pid ", pid)
log.Info("openlist already started, pid ", pid)
return
}
}
args := os.Args
args[1] = "server"
args = append(args, "--force-bin-dir")
cmd := &exec.Cmd{
Path: args[0],
Args: args,
Env: os.Environ(),
exe, err := os.Executable()
if err != nil {
log.Fatal("failed to resolve executable path: ", err)
}
childArgs := append([]string{"server"}, os.Args[2:]...)
hasForceBinDir := false
for _, arg := range childArgs {
if arg == "--force-bin-dir" || strings.HasPrefix(arg, "--force-bin-dir=") {
hasForceBinDir = true
break
}
}
if !hasForceBinDir {
childArgs = append(childArgs, "--force-bin-dir")
}
cmd := exec.Command(exe, childArgs...)
cmd.Env = os.Environ()
stdout, err := os.OpenFile(filepath.Join(filepath.Dir(pidFile), "start.log"), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
log.Fatal(os.Getpid(), ": failed to open start log file:", err)
@@ -52,7 +62,7 @@ func start() {
log.Infof("success start pid: %d", cmd.Process.Pid)
err = os.WriteFile(pidFile, []byte(strconv.Itoa(cmd.Process.Pid)), 0666)
if err != nil {
log.Warn("failed to record pid, you may not be able to stop the program with `./alist stop`")
log.Warn("failed to record pid, you may not be able to stop the program with `./openlist stop`")
}
}
+8 -8
View File
@@ -1,10 +1,10 @@
/*
Copyright © 2022 NAME HERE <EMAIL ADDRESS>
*/
//go:build !windows
package cmd
import (
"os"
"syscall"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -13,7 +13,7 @@ import (
// StopCmd represents the stop command
var StopCmd = &cobra.Command{
Use: "stop",
Short: "Stop alist server by daemon/pid file",
Short: "Stop openlist server by daemon/pid file",
Run: func(cmd *cobra.Command, args []string) {
stop()
},
@@ -22,7 +22,7 @@ var StopCmd = &cobra.Command{
func stop() {
initDaemon()
if pid == -1 {
log.Info("Seems not have been started. Try use `alist start` to start server.")
log.Info("Seems not have been started. Try use `openlist start` to start server.")
return
}
process, err := os.FindProcess(pid)
@@ -30,11 +30,11 @@ func stop() {
log.Errorf("failed to find process by pid: %d, reason: %v", pid, process)
return
}
err = process.Kill()
err = process.Signal(syscall.SIGTERM)
if err != nil {
log.Errorf("failed to kill process %d: %v", pid, err)
log.Errorf("failed to terminate process %d: %v", pid, err)
} else {
log.Info("killed process: ", pid)
log.Info("terminated process: ", pid)
}
err = os.Remove(pidFile)
if err != nil {
+34
View File
@@ -0,0 +1,34 @@
//go:build windows
package cmd
import (
"github.com/spf13/cobra"
)
// StopCmd represents the stop command
var StopCmd = &cobra.Command{
Use: "stop",
Short: "Same as the kill command",
Run: func(cmd *cobra.Command, args []string) {
stop()
},
}
func stop() {
kill()
}
func init() {
RootCmd.AddCommand(StopCmd)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// stopCmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// stopCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
+61 -23
View File
@@ -4,11 +4,13 @@ Copyright © 2023 NAME HERE <EMAIL ADDRESS>
package cmd
import (
"fmt"
"os"
"strconv"
"github.com/alist-org/alist/v3/internal/db"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/OpenListTeam/OpenList/v4/internal/bootstrap"
"github.com/OpenListTeam/OpenList/v4/internal/db"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
"github.com/charmbracelet/bubbles/table"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
@@ -22,28 +24,61 @@ var storageCmd = &cobra.Command{
}
var disableStorageCmd = &cobra.Command{
Use: "disable",
Short: "Disable a storage",
Run: func(cmd *cobra.Command, args []string) {
Use: "disable [mount path]",
Short: "Disable a storage by mount path",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
utils.Log.Errorf("mount path is required")
return
return fmt.Errorf("mount path is required")
}
mountPath := args[0]
Init()
defer Release()
bootstrap.Init()
defer bootstrap.Release()
storage, err := db.GetStorageByMountPath(mountPath)
if err != nil {
utils.Log.Errorf("failed to query storage: %+v", err)
} else {
storage.Disabled = true
err = db.UpdateStorage(storage)
if err != nil {
utils.Log.Errorf("failed to update storage: %+v", err)
} else {
utils.Log.Infof("Storage with mount path [%s] have been disabled", mountPath)
return fmt.Errorf("failed to query storage: %+v", err)
}
storage.Disabled = true
err = db.UpdateStorage(storage)
if err != nil {
return fmt.Errorf("failed to update storage: %+v", err)
}
utils.Log.Infof("Storage with mount path [%s] has been disabled from CLI", mountPath)
fmt.Printf("Storage with mount path [%s] has been disabled\n", mountPath)
return nil
},
}
var deleteStorageCmd = &cobra.Command{
Use: "delete [id]",
Short: "Delete a storage by id",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("id is required")
}
id, err := strconv.Atoi(args[0])
if err != nil {
return fmt.Errorf("id must be a number")
}
if force, _ := cmd.Flags().GetBool("force"); force {
fmt.Printf("Are you sure you want to delete storage with id [%d]? [y/N]: ", id)
var confirm string
fmt.Scanln(&confirm)
if confirm != "y" && confirm != "Y" {
fmt.Println("Delete operation cancelled.")
return nil
}
}
bootstrap.Init()
defer bootstrap.Release()
err = db.DeleteStorageById(uint(id))
if err != nil {
return fmt.Errorf("failed to delete storage by id: %+v", err)
}
utils.Log.Infof("Storage with id [%d] have been deleted from CLI", id)
fmt.Printf("Storage with id [%d] have been deleted\n", id)
return nil
},
}
@@ -88,14 +123,14 @@ var storageTableHeight int
var listStorageCmd = &cobra.Command{
Use: "list",
Short: "List all storages",
Run: func(cmd *cobra.Command, args []string) {
Init()
defer Release()
RunE: func(cmd *cobra.Command, args []string) error {
bootstrap.Init()
defer bootstrap.Release()
storages, _, err := db.GetStorages(1, -1)
if err != nil {
utils.Log.Errorf("failed to query storages: %+v", err)
return fmt.Errorf("failed to query storages: %+v", err)
} else {
utils.Log.Infof("Found %d storages", len(storages))
fmt.Printf("Found %d storages\n", len(storages))
columns := []table.Column{
{Title: "ID", Width: 4},
{Title: "Driver", Width: 16},
@@ -138,10 +173,11 @@ var listStorageCmd = &cobra.Command{
m := model{t}
if _, err := tea.NewProgram(m).Run(); err != nil {
utils.Log.Errorf("failed to run program: %+v", err)
fmt.Printf("failed to run program: %+v\n", err)
os.Exit(1)
}
}
return nil
},
}
@@ -151,6 +187,8 @@ func init() {
storageCmd.AddCommand(disableStorageCmd)
storageCmd.AddCommand(listStorageCmd)
storageCmd.PersistentFlags().IntVarP(&storageTableHeight, "height", "H", 10, "Table height")
storageCmd.AddCommand(deleteStorageCmd)
deleteStorageCmd.Flags().BoolP("force", "f", false, "Force delete without confirmation")
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
+4 -4
View File
@@ -5,10 +5,10 @@ import (
"fmt"
"time"
"github.com/alist-org/alist/v3/internal/conf"
"github.com/alist-org/alist/v3/internal/op"
"github.com/alist-org/alist/v3/internal/setting"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/OpenListTeam/OpenList/v4/internal/conf"
"github.com/OpenListTeam/OpenList/v4/internal/op"
"github.com/OpenListTeam/OpenList/v4/internal/setting"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
"github.com/go-resty/resty/v2"
)
+6 -4
View File
@@ -6,24 +6,26 @@ package cmd
import (
"fmt"
"os"
"runtime"
"github.com/alist-org/alist/v3/internal/conf"
"github.com/OpenListTeam/OpenList/v4/internal/conf"
"github.com/spf13/cobra"
)
// VersionCmd represents the version command
var VersionCmd = &cobra.Command{
Use: "version",
Short: "Show current version of AList",
Short: "Show current version of OpenList",
Run: func(cmd *cobra.Command, args []string) {
goVersion := fmt.Sprintf("%s %s/%s", runtime.Version(), runtime.GOOS, runtime.GOARCH)
fmt.Printf(`Built At: %s
Go Version: %s
Author: %s
Commit ID: %s
Version: %s
WebVersion: %s
`,
conf.BuiltAt, conf.GoVersion, conf.GitAuthor, conf.GitCommit, conf.Version, conf.WebVersion)
`, conf.BuiltAt, goVersion, conf.GitAuthor, conf.GitCommit, conf.Version, conf.WebVersion)
os.Exit(0)
},
}
+6 -8
View File
@@ -1,16 +1,14 @@
version: '3.3'
services:
alist:
openlist:
restart: always
volumes:
- '/etc/alist:/opt/alist/data'
- '/etc/openlist:/opt/openlist/data'
ports:
- '5244:5244'
- '5245:5245'
user: '0:0'
environment:
- PUID=0
- PGID=0
- UMASK=022
- TZ=UTC
container_name: alist
image: 'xhofe/alist:latest'
- TZ=Asia/Shanghai
container_name: openlist
image: 'openlistteam/openlist:latest'
+33 -16
View File
@@ -1,43 +1,60 @@
package _115
import (
"errors"
"github.com/OpenListTeam/OpenList/v4/drivers/base"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
driver115 "github.com/SheltonZhu/115driver/pkg/driver"
"github.com/alist-org/alist/v3/drivers/base"
log "github.com/sirupsen/logrus"
)
var (
md5Salt = "Qclm8MGWUv59TnrR0XPg"
appVer = "27.0.5.7"
appVer = "35.6.0.3"
)
func (d *Pan115) getAppVersion() ([]driver115.AppVersion, error) {
result := driver115.VersionResp{}
resp, err := base.RestyClient.R().Get(driver115.ApiGetVersion)
err = driver115.CheckErr(err, &result, resp)
func (d *Pan115) getAppVersion() (string, error) {
result := VersionResp{}
res, err := base.RestyClient.R().Get(driver115.ApiGetVersion)
if err != nil {
return nil, err
return "", err
}
return result.Data.GetAppVersions(), nil
err = utils.Json.Unmarshal(res.Body(), &result)
if err != nil {
return "", err
}
if len(result.Error) > 0 {
return "", errors.New(result.Error)
}
return result.Data.Win.Version, nil
}
func (d *Pan115) getAppVer() string {
// todo add some cache?
vers, err := d.getAppVersion()
ver, err := d.getAppVersion()
if err != nil {
log.Warnf("[115] get app version failed: %v", err)
return appVer
}
for _, ver := range vers {
if ver.AppName == "win" {
return ver.Version
}
if len(ver) > 0 {
return ver
}
return appVer
}
func (d *Pan115) initAppVer() {
appVer = d.getAppVer()
log.Debugf("use app version: %v", appVer)
}
type VersionResp struct {
Error string `json:"error,omitempty"`
Data Versions `json:"data"`
}
type Versions struct {
Win Version `json:"win"`
}
type Version struct {
Version string `json:"version_code"`
}
+96 -45
View File
@@ -2,15 +2,15 @@ package _115
import (
"context"
"fmt"
"strings"
"sync"
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/model"
streamPkg "github.com/OpenListTeam/OpenList/v4/internal/stream"
"github.com/OpenListTeam/OpenList/v4/pkg/http_range"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
driver115 "github.com/SheltonZhu/115driver/pkg/driver"
"github.com/alist-org/alist/v3/internal/driver"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/pkg/http_range"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/pkg/errors"
"golang.org/x/time/rate"
)
@@ -68,8 +68,7 @@ func (d *Pan115) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
return nil, err
}
userAgent := args.Header.Get("User-Agent")
downloadInfo, err := d.
DownloadWithUA(file.(*FileObj).PickCode, userAgent)
downloadInfo, err := d.client.DownloadWithUA(file.(*FileObj).PickCode, userAgent)
if err != nil {
return nil, err
}
@@ -80,28 +79,60 @@ func (d *Pan115) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
return link, nil
}
func (d *Pan115) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
func (d *Pan115) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) (model.Obj, error) {
if err := d.WaitLimit(ctx); err != nil {
return err
return nil, err
}
if _, err := d.client.Mkdir(parentDir.GetID(), dirName); err != nil {
return err
result := driver115.MkdirResp{}
form := map[string]string{
"pid": parentDir.GetID(),
"cname": dirName,
}
return nil
req := d.client.NewRequest().
SetFormData(form).
SetResult(&result).
ForceContentType("application/json;charset=UTF-8")
resp, err := req.Post(driver115.ApiDirAdd)
err = driver115.CheckErr(err, &result, resp)
if err != nil {
return nil, err
}
f, err := d.getNewFile(result.FileID)
if err != nil {
return nil, nil
}
return f, nil
}
func (d *Pan115) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
func (d *Pan115) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
if err := d.WaitLimit(ctx); err != nil {
return err
return nil, err
}
return d.client.Move(dstDir.GetID(), srcObj.GetID())
if err := d.client.Move(dstDir.GetID(), srcObj.GetID()); err != nil {
return nil, err
}
f, err := d.getNewFile(srcObj.GetID())
if err != nil {
return nil, nil
}
return f, nil
}
func (d *Pan115) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
func (d *Pan115) Rename(ctx context.Context, srcObj model.Obj, newName string) (model.Obj, error) {
if err := d.WaitLimit(ctx); err != nil {
return err
return nil, err
}
return d.client.Rename(srcObj.GetID(), newName)
if err := d.client.Rename(srcObj.GetID(), newName); err != nil {
return nil, err
}
f, err := d.getNewFile((srcObj.GetID()))
if err != nil {
return nil, nil
}
return f, nil
}
func (d *Pan115) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
@@ -118,24 +149,21 @@ func (d *Pan115) Remove(ctx context.Context, obj model.Obj) error {
return d.client.Delete(obj.GetID())
}
func (d *Pan115) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
func (d *Pan115) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) (model.Obj, error) {
if err := d.WaitLimit(ctx); err != nil {
return err
return nil, err
}
if stream.GetSize() > utils.GB*20 { // TODO 由于官方分片上传接口失效,所以使用普通上传小于20GB的文件
return fmt.Errorf("unsupported file size: 20GB limit exceeded")
}
// 分片上传
var (
fastInfo *driver115.UploadInitResp
dirID = dstDir.GetID()
)
if ok, err := d.client.UploadAvailable(); err != nil || !ok {
return err
return nil, err
}
if stream.GetSize() > d.client.UploadMetaInfo.SizeLimit {
return driver115.ErrUploadTooLarge
return nil, driver115.ErrUploadTooLarge
}
//if digest, err = d.client.GetDigestResult(stream); err != nil {
// return err
@@ -148,22 +176,18 @@ func (d *Pan115) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
}
reader, err := stream.RangeRead(http_range.Range{Start: 0, Length: hashSize})
if err != nil {
return err
return nil, err
}
preHash, err := utils.HashReader(utils.SHA1, reader)
if err != nil {
return err
return nil, err
}
preHash = strings.ToUpper(preHash)
fullHash := stream.GetHash().GetHash(utils.SHA1)
if len(fullHash) <= 0 {
tmpF, err := stream.CacheFullInTempFile()
if len(fullHash) != utils.SHA1.Width {
_, fullHash, err = streamPkg.CacheFullAndHash(stream, &up, utils.SHA1)
if err != nil {
return err
}
fullHash, err = utils.HashFile(utils.SHA1, tmpF)
if err != nil {
return err
return nil, err
}
}
fullHash = strings.ToUpper(fullHash)
@@ -172,22 +196,36 @@ func (d *Pan115) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
// note that 115 add timeout for rapid-upload,
// and "sig invalid" err is thrown even when the hash is correct after timeout.
if fastInfo, err = d.rapidUpload(stream.GetSize(), stream.GetName(), dirID, preHash, fullHash, stream); err != nil {
return err
return nil, err
}
if matched, err := fastInfo.Ok(); err != nil {
return err
return nil, err
} else if matched {
return nil
f, err := d.getNewFileByPickCode(fastInfo.PickCode)
if err != nil {
return nil, nil
}
return f, nil
}
var uploadResult *UploadResult
// 闪传失败,上传
// if stream.GetSize() <= utils.KB{ // 文件大小小于1KB,改用普通模式上传
if stream.GetSize() <= utils.GB*20 { // TODO 由于官方分片上传接口失效,所以使用普通上传小于20GB的文件
return d.client.UploadByOSS(&fastInfo.UploadOSSParams, stream, dirID)
if stream.GetSize() <= 10*utils.MB { // 文件大小小于10MB,改用普通模式上传
if uploadResult, err = d.UploadByOSS(ctx, &fastInfo.UploadOSSParams, stream, dirID, up); err != nil {
return nil, err
}
} else {
// 分片上传
if uploadResult, err = d.UploadByMultipart(ctx, &fastInfo.UploadOSSParams, stream.GetSize(), stream, dirID, up); err != nil {
return nil, err
}
}
return driver115.ErrUnexpected
// 分片上传
// return d.UploadByMultipart(&fastInfo.UploadOSSParams, stream.GetSize(), stream, dirID)
file, err := d.getNewFile(uploadResult.Data.FileID)
if err != nil {
return nil, nil
}
return file, nil
}
func (d *Pan115) OfflineList(ctx context.Context) ([]*driver115.OfflineTask, error) {
@@ -199,11 +237,24 @@ func (d *Pan115) OfflineList(ctx context.Context) ([]*driver115.OfflineTask, err
}
func (d *Pan115) OfflineDownload(ctx context.Context, uris []string, dstDir model.Obj) ([]string, error) {
return d.client.AddOfflineTaskURIs(uris, dstDir.GetID())
return d.client.AddOfflineTaskURIs(uris, dstDir.GetID(), driver115.WithAppVer(appVer))
}
func (d *Pan115) DeleteOfflineTasks(ctx context.Context, hashes []string, deleteFiles bool) error {
return d.client.DeleteOfflineTasks(hashes, deleteFiles)
}
func (d *Pan115) GetDetails(ctx context.Context) (*model.StorageDetails, error) {
info, err := d.client.GetInfo()
if err != nil {
return nil, err
}
return &model.StorageDetails{
DiskUsage: model.DiskUsage{
TotalSpace: info.SpaceInfo.AllTotal.Size,
UsedSpace: info.SpaceInfo.AllUse.Size,
},
}, nil
}
var _ driver.Driver = (*Pan115)(nil)
+6 -8
View File
@@ -1,8 +1,8 @@
package _115
import (
"github.com/alist-org/alist/v3/internal/driver"
"github.com/alist-org/alist/v3/internal/op"
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/op"
)
type Addition struct {
@@ -10,16 +10,14 @@ type Addition struct {
QRCodeToken string `json:"qrcode_token" type:"text" help:"one of QR code token and cookie required"`
QRCodeSource string `json:"qrcode_source" type:"select" options:"web,android,ios,tv,alipaymini,wechatmini,qandroid" default:"linux" help:"select the QR code device, default linux"`
PageSize int64 `json:"page_size" type:"number" default:"1000" help:"list api per page size of 115 driver"`
LimitRate float64 `json:"limit_rate" type:"number" default:"2" help:"limit all api request rate (1r/[limit_rate]s)"`
LimitRate float64 `json:"limit_rate" type:"float" default:"2" help:"limit all api request rate ([limit]r/1s)"`
driver.RootID
}
var config = driver.Config{
Name: "115 Cloud",
DefaultRoot: "0",
// OnlyProxy: true,
// OnlyLocal: true,
// NoOverwriteUpload: true,
Name: "115 Cloud",
DefaultRoot: "0",
LinkCacheMode: driver.LinkCacheUA,
}
func init() {
+6 -2
View File
@@ -3,9 +3,9 @@ package _115
import (
"time"
"github.com/OpenListTeam/OpenList/v4/internal/model"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
"github.com/SheltonZhu/115driver/pkg/driver"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/pkg/utils"
)
var _ model.Obj = (*FileObj)(nil)
@@ -22,6 +22,10 @@ func (f *FileObj) GetHash() utils.HashInfo {
return utils.NewHashInfo(utils.SHA1, f.Sha1)
}
func (f *FileObj) Thumb() string {
return f.ThumbURL
}
type UploadResult struct {
driver.BasicResp
Data struct {
+98 -82
View File
@@ -2,33 +2,33 @@ package _115
import (
"bytes"
"context"
"crypto/md5"
"crypto/tls"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
"github.com/alist-org/alist/v3/internal/conf"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/pkg/http_range"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
"github.com/OpenListTeam/OpenList/v4/internal/conf"
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/model"
netutil "github.com/OpenListTeam/OpenList/v4/internal/net"
"github.com/OpenListTeam/OpenList/v4/pkg/http_range"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
cipher "github.com/SheltonZhu/115driver/pkg/crypto/ec115"
driver115 "github.com/SheltonZhu/115driver/pkg/driver"
crypto "github.com/gaoyb7/115drive-webdav/115"
"github.com/orzogc/fake115uploader/cipher"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
"github.com/pkg/errors"
)
//var UserAgent = driver115.UA115Browser
// var UserAgent = driver115.UA115Browser
func (d *Pan115) login() error {
var err error
opts := []driver115.Option{
@@ -46,7 +46,7 @@ func (d *Pan115) login() error {
if cr, err = d.client.QRCodeLoginWithApp(s, driver115.LoginApp(d.QRCodeSource)); err != nil {
return errors.Wrap(err, "failed to login by qrcode")
}
d.Cookie = fmt.Sprintf("UID=%s;CID=%s;SEID=%s", cr.UID, cr.CID, cr.SEID)
d.Cookie = fmt.Sprintf("UID=%s;CID=%s;SEID=%s;KID=%s", cr.UID, cr.CID, cr.SEID, cr.KID)
d.QRCodeToken = ""
} else if d.Cookie != "" {
if err = cr.FromCookie(d.Cookie); err != nil {
@@ -64,7 +64,7 @@ func (d *Pan115) getFiles(fileId string) ([]FileObj, error) {
if d.PageSize <= 0 {
d.PageSize = driver115.FileListLimit
}
files, err := d.client.ListWithLimit(fileId, d.PageSize)
files, err := d.client.ListWithLimit(fileId, d.PageSize, driver115.WithMultiUrls())
if err != nil {
return nil, err
}
@@ -74,63 +74,36 @@ func (d *Pan115) getFiles(fileId string) ([]FileObj, error) {
return res, nil
}
func (d *Pan115) getUA() string {
return fmt.Sprintf("Mozilla/5.0 115Browser/%s", appVer)
func (d *Pan115) getNewFile(fileId string) (*FileObj, error) {
file, err := d.client.GetFile(fileId)
if err != nil {
return nil, err
}
return &FileObj{*file}, nil
}
func (d *Pan115) DownloadWithUA(pickCode, ua string) (*driver115.DownloadInfo, error) {
key := crypto.GenerateKey()
result := driver115.DownloadResp{}
params, err := utils.Json.Marshal(map[string]string{"pickcode": pickCode})
if err != nil {
func (d *Pan115) getNewFileByPickCode(pickCode string) (*FileObj, error) {
result := driver115.GetFileInfoResponse{}
req := d.client.NewRequest().
SetQueryParam("pick_code", pickCode).
ForceContentType("application/json;charset=UTF-8").
SetResult(&result)
resp, err := req.Get(driver115.ApiFileInfo)
if err := driver115.CheckErr(err, &result, resp); err != nil {
return nil, err
}
data := crypto.Encode(params, key)
bodyReader := strings.NewReader(url.Values{"data": []string{data}}.Encode())
reqUrl := fmt.Sprintf("%s?t=%s", driver115.ApiDownloadGetUrl, driver115.Now().String())
req, _ := http.NewRequest(http.MethodPost, reqUrl, bodyReader)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Cookie", d.Cookie)
req.Header.Set("User-Agent", ua)
resp, err := d.client.Client.GetClient().Do(req)
if err != nil {
return nil, err
if len(result.Files) == 0 {
return nil, errors.New("not get file info")
}
defer resp.Body.Close()
fileInfo := result.Files[0]
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if err := utils.Json.Unmarshal(body, &result); err != nil {
return nil, err
}
f := &FileObj{}
f.From(fileInfo)
return f, nil
}
if err = result.Err(string(body)); err != nil {
return nil, err
}
bytes, err := crypto.Decode(string(result.EncodedData), key)
if err != nil {
return nil, err
}
downloadInfo := driver115.DownloadData{}
if err := utils.Json.Unmarshal(bytes, &downloadInfo); err != nil {
return nil, err
}
for _, info := range downloadInfo {
if info.FileSize < 0 {
return nil, driver115.ErrDownloadEmpty
}
info.Header = resp.Request.Header
return info, nil
}
return nil, driver115.ErrUnexpected
func (d *Pan115) getUA() string {
return fmt.Sprintf("Mozilla/5.0 115Browser/%s", appVer)
}
func (c *Pan115) GenerateToken(fileID, preID, timeStamp, fileSize, signKey, signVal string) string {
@@ -244,8 +217,44 @@ func UploadDigestRange(stream model.FileStreamer, rangeSpec string) (result stri
return
}
// UploadByOSS use aliyun sdk to upload
func (c *Pan115) UploadByOSS(ctx context.Context, params *driver115.UploadOSSParams, s model.FileStreamer, dirID string, up driver.UpdateProgress) (*UploadResult, error) {
ossToken, err := c.client.GetOSSToken()
if err != nil {
return nil, err
}
ossClient, err := netutil.NewOSSClient(driver115.OSSEndpoint, ossToken.AccessKeyID, ossToken.AccessKeySecret)
if err != nil {
return nil, err
}
bucket, err := ossClient.Bucket(params.Bucket)
if err != nil {
return nil, err
}
var bodyBytes []byte
r := driver.NewLimitedUploadStream(ctx, &driver.ReaderUpdatingProgress{
Reader: s,
UpdateProgress: up,
})
if err = bucket.PutObject(params.Object, r, append(
driver115.OssOption(params, ossToken),
oss.CallbackResult(&bodyBytes),
)...); err != nil {
return nil, err
}
var uploadResult UploadResult
if err = json.Unmarshal(bodyBytes, &uploadResult); err != nil {
return nil, err
}
return &uploadResult, uploadResult.Err(string(bodyBytes))
}
// UploadByMultipart upload by mutipart blocks
func (d *Pan115) UploadByMultipart(params *driver115.UploadOSSParams, fileSize int64, stream model.FileStreamer, dirID string, opts ...driver115.UploadMultipartOption) error {
func (d *Pan115) UploadByMultipart(ctx context.Context, params *driver115.UploadOSSParams, fileSize int64, s model.FileStreamer,
dirID string, up driver.UpdateProgress, opts ...driver115.UploadMultipartOption,
) (*UploadResult, error) {
var (
chunks []oss.FileChunk
parts []oss.UploadPart
@@ -257,9 +266,9 @@ func (d *Pan115) UploadByMultipart(params *driver115.UploadOSSParams, fileSize i
err error
)
tmpF, err := stream.CacheFullInTempFile()
tmpF, err := s.CacheFullAndWriter(&up, nil)
if err != nil {
return err
return nil, err
}
options := driver115.DefalutUploadMultipartOptions()
@@ -272,15 +281,15 @@ func (d *Pan115) UploadByMultipart(params *driver115.UploadOSSParams, fileSize i
options.ThreadsNum = 1
if ossToken, err = d.client.GetOSSToken(); err != nil {
return err
return nil, err
}
if ossClient, err = oss.New(driver115.OSSEndpoint, ossToken.AccessKeyID, ossToken.AccessKeySecret, oss.EnableMD5(true), oss.EnableCRC(true)); err != nil {
return err
if ossClient, err = netutil.NewOSSClient(driver115.OSSEndpoint, ossToken.AccessKeyID, ossToken.AccessKeySecret, oss.EnableMD5(true), oss.EnableCRC(true)); err != nil {
return nil, err
}
if bucket, err = ossClient.Bucket(params.Bucket); err != nil {
return err
return nil, err
}
// ossToken一小时后就会失效,所以每50分钟重新获取一次
@@ -290,7 +299,7 @@ func (d *Pan115) UploadByMultipart(params *driver115.UploadOSSParams, fileSize i
timeout := time.NewTimer(options.Timeout)
if chunks, err = SplitFile(fileSize); err != nil {
return err
return nil, err
}
if imur, err = bucket.InitiateMultipartUpload(params.Object,
@@ -298,7 +307,7 @@ func (d *Pan115) UploadByMultipart(params *driver115.UploadOSSParams, fileSize i
oss.UserAgentHeader(driver115.OSSUserAgent),
oss.EnableSha1(), oss.Sequential(),
); err != nil {
return err
return nil, err
}
wg := sync.WaitGroup{}
@@ -316,6 +325,7 @@ func (d *Pan115) UploadByMultipart(params *driver115.UploadOSSParams, fileSize i
quit <- struct{}{}
}()
completedNum := atomic.Int32{}
// consumers
for i := 0; i < options.ThreadsNum; i++ {
go func(threadId int) {
@@ -327,6 +337,10 @@ func (d *Pan115) UploadByMultipart(params *driver115.UploadOSSParams, fileSize i
for chunk := range chunksCh {
var part oss.UploadPart // 出现错误就继续尝试,共尝试3次
for retry := 0; retry < 3; retry++ {
if utils.IsCanceled(ctx) {
err = ctx.Err()
break
}
select {
case <-ticker.C:
if ossToken, err = d.client.GetOSSToken(); err != nil { // 到时重新获取ossToken
@@ -334,18 +348,20 @@ func (d *Pan115) UploadByMultipart(params *driver115.UploadOSSParams, fileSize i
}
default:
}
buf := make([]byte, chunk.Size)
if _, err = tmpF.ReadAt(buf, chunk.Offset); err != nil && !errors.Is(err, io.EOF) {
continue
}
if part, err = bucket.UploadPart(imur, bytes.NewBuffer(buf), chunk.Size, chunk.Number, driver115.OssOption(params, ossToken)...); err == nil {
if part, err = bucket.UploadPart(imur, driver.NewLimitedUploadStream(ctx, bytes.NewReader(buf)),
chunk.Size, chunk.Number, driver115.OssOption(params, ossToken)...); err == nil {
break
}
}
if err != nil {
errCh <- errors.Wrap(err, fmt.Sprintf("上传 %s 的第%d个分片时出现错误:%v", stream.GetName(), chunk.Number, err))
errCh <- errors.Wrap(err, fmt.Sprintf("上传 %s 的第%d个分片时出现错误:%v", s.GetName(), chunk.Number, err))
} else {
num := completedNum.Add(1)
up(float64(num) * 100.0 / float64(len(chunks)))
}
UploadedPartsCh <- part
}
@@ -364,14 +380,14 @@ LOOP:
case <-ticker.C:
// 到时重新获取ossToken
if ossToken, err = d.client.GetOSSToken(); err != nil {
return err
return nil, err
}
case <-quit:
break LOOP
case <-errCh:
return err
return nil, err
case <-timeout.C:
return fmt.Errorf("time out")
return nil, fmt.Errorf("time out")
}
}
@@ -381,14 +397,14 @@ LOOP:
driver115.OssOption(params, ossToken),
oss.CallbackResult(&bodyBytes),
)...); err != nil {
return err
return nil, err
}
var uploadResult UploadResult
if err = json.Unmarshal(bodyBytes, &uploadResult); err != nil {
return err
return nil, err
}
return uploadResult.Err(string(bodyBytes))
return &uploadResult, uploadResult.Err(string(bodyBytes))
}
func chunksProducer(ch chan oss.FileChunk, chunks []oss.FileChunk) {
+461
View File
@@ -0,0 +1,461 @@
package _115_open
import (
"context"
"errors"
"fmt"
"net/http"
stdpath "path"
"slices"
"strconv"
"strings"
"time"
sdk "github.com/OpenListTeam/115-sdk-go"
"github.com/OpenListTeam/OpenList/v4/cmd/flags"
"github.com/OpenListTeam/OpenList/v4/drivers/base"
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/errs"
"github.com/OpenListTeam/OpenList/v4/internal/model"
"github.com/OpenListTeam/OpenList/v4/internal/op"
"github.com/OpenListTeam/OpenList/v4/internal/stream"
"github.com/OpenListTeam/OpenList/v4/pkg/http_range"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
"golang.org/x/time/rate"
)
type Open115 struct {
model.Storage
Addition
client *sdk.Client
limiter *rate.Limiter
parentPath string
}
func (d *Open115) Config() driver.Config {
return config
}
func (d *Open115) GetAddition() driver.Additional {
return &d.Addition
}
func (d *Open115) Init(ctx context.Context) error {
d.client = sdk.New(sdk.WithRefreshToken(d.Addition.RefreshToken),
sdk.WithAccessToken(d.Addition.AccessToken),
sdk.WithOnRefreshToken(func(s1, s2 string) {
d.Addition.AccessToken = s1
d.Addition.RefreshToken = s2
op.MustSaveDriverStorage(d)
}))
if flags.Debug || flags.Dev {
d.client.SetDebug(true)
}
_, err := d.client.UserInfo(ctx)
if err != nil {
return err
}
if d.Addition.LimitRate > 0 {
d.limiter = rate.NewLimiter(rate.Limit(d.Addition.LimitRate), 1)
}
if d.PageSize <= 0 {
d.PageSize = 200
} else if d.PageSize > 1150 {
d.PageSize = 1150
}
// add parent path
d.parentPath = "/"
if d.GetRootId() != d.Config().DefaultRoot {
folderInfo, err := d.client.GetFolderInfo(ctx, d.GetRootId())
if err != nil {
return err
}
if folderInfo.FileID != d.Config().DefaultRoot {
d.parentPath = stdpath.Join(d.parentPath, folderInfo.FileName)
}
parentPaths := folderInfo.Paths
slices.Reverse(parentPaths)
for _, parentPathInfo := range parentPaths {
if parentPathInfo.FileID == d.Config().DefaultRoot {
d.parentPath = stdpath.Join("/", d.parentPath)
} else {
d.parentPath = stdpath.Join("/", parentPathInfo.FileName, d.parentPath)
}
}
}
return nil
}
func (d *Open115) WaitLimit(ctx context.Context) error {
if d.limiter != nil {
return d.limiter.Wait(ctx)
}
return nil
}
func (d *Open115) Drop(ctx context.Context) error {
return nil
}
func (d *Open115) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
var res []model.Obj
pageSize := int64(d.PageSize)
offset := int64(0)
for {
if err := d.WaitLimit(ctx); err != nil {
return nil, err
}
resp, err := d.client.GetFiles(ctx, &sdk.GetFilesReq{
CID: dir.GetID(),
Limit: pageSize,
Offset: offset,
ASC: d.Addition.OrderDirection == "asc",
O: d.Addition.OrderBy,
// Cur: 1,
ShowDir: true,
})
if err != nil {
return nil, err
}
res = append(res, utils.MustSliceConvert(resp.Data, func(src sdk.GetFilesResp_File) model.Obj {
obj := Obj(src)
return &obj
})...)
if len(res) >= int(resp.Count) {
break
}
offset += pageSize
}
return res, nil
}
func (d *Open115) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
if err := d.WaitLimit(ctx); err != nil {
return nil, err
}
var ua string
if args.Header != nil {
ua = args.Header.Get("User-Agent")
}
if ua == "" {
ua = base.UserAgent
}
obj, ok := file.(*Obj)
if !ok {
return nil, fmt.Errorf("can't convert obj")
}
pc := obj.Pc
resp, err := d.client.DownURL(ctx, pc, ua)
if err != nil {
return nil, err
}
u, ok := resp[obj.GetID()]
if !ok {
return nil, fmt.Errorf("can't get link")
}
return &model.Link{
URL: u.URL.URL,
Header: http.Header{
"User-Agent": []string{ua},
},
}, nil
}
func (d *Open115) Get(ctx context.Context, path string) (model.Obj, error) {
if err := d.WaitLimit(ctx); err != nil {
return nil, err
}
path = stdpath.Join(d.parentPath, path)
resp, err := d.client.GetFolderInfoByPath(ctx, path)
if err != nil {
if errors.Is(err, sdk.ErrObjectNotFound) {
return d.getFromParent(ctx, path, "")
}
return nil, err
}
obj := &Obj{
Fid: resp.FileID,
Fn: resp.FileName,
Fc: resp.FileCategory,
Sha1: resp.Sha1,
Pc: resp.PickCode,
FS: resp.SizeByte,
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) {
if err := d.WaitLimit(ctx); err != nil {
return nil, err
}
resp, err := d.client.Mkdir(ctx, parentDir.GetID(), dirName)
if err != nil {
return nil, err
}
return &Obj{
Fid: resp.FileID,
Pid: parentDir.GetID(),
Fn: dirName,
Fc: "0",
Upt: time.Now().Unix(),
Uet: time.Now().Unix(),
UpPt: time.Now().Unix(),
}, nil
}
func (d *Open115) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
if err := d.WaitLimit(ctx); err != nil {
return err
}
_, err := d.client.Move(ctx, &sdk.MoveReq{
FileIDs: srcObj.GetID(),
ToCid: dstDir.GetID(),
})
return err
}
func (d *Open115) Rename(ctx context.Context, srcObj model.Obj, newName string) (model.Obj, error) {
if err := d.WaitLimit(ctx); err != nil {
return nil, err
}
_, err := d.client.UpdateFile(ctx, &sdk.UpdateFileReq{
FileID: srcObj.GetID(),
FileName: newName,
})
if err != nil {
return nil, err
}
obj, ok := srcObj.(*Obj)
if ok {
obj.Fn = newName
return srcObj, nil
}
return nil, nil
}
func (d *Open115) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
if err := d.WaitLimit(ctx); err != nil {
return err
}
_, err := d.client.Copy(ctx, &sdk.CopyReq{
PID: dstDir.GetID(),
FileID: srcObj.GetID(),
NoDupli: "1",
})
return err
}
func (d *Open115) Remove(ctx context.Context, obj model.Obj) error {
if err := d.WaitLimit(ctx); err != nil {
return err
}
_obj, ok := obj.(*Obj)
if !ok {
return fmt.Errorf("can't convert obj")
}
_, err := d.client.DelFile(ctx, &sdk.DelFileReq{
FileIDs: _obj.GetID(),
ParentID: _obj.Pid,
})
if err != nil {
return err
}
return nil
}
func (d *Open115) Put(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) error {
err := d.WaitLimit(ctx)
if err != nil {
return err
}
sha1 := file.GetHash().GetHash(utils.SHA1)
if len(sha1) != utils.SHA1.Width {
_, sha1, err = stream.CacheFullAndHash(file, &up, utils.SHA1)
if err != nil {
return err
}
}
const PreHashSize int64 = 128 * utils.KB
hashSize := PreHashSize
if file.GetSize() < PreHashSize {
hashSize = file.GetSize()
}
reader, err := file.RangeRead(http_range.Range{Start: 0, Length: hashSize})
if err != nil {
return err
}
sha1128k, err := utils.HashReader(utils.SHA1, reader)
if err != nil {
return err
}
// 1. Init
resp, err := d.client.UploadInit(ctx, &sdk.UploadInitReq{
FileName: file.GetName(),
FileSize: file.GetSize(),
Target: dstDir.GetID(),
FileID: strings.ToUpper(sha1),
PreID: strings.ToUpper(sha1128k),
})
if err != nil {
return err
}
if resp.Status == 2 {
up(100)
return nil
}
// 2. two way verify
if utils.SliceContains([]int{6, 7, 8}, resp.Status) {
signCheck := strings.Split(resp.SignCheck, "-") //"sign_check": "2392148-2392298" 取2392148-2392298之间的内容(包含2392148、2392298)的sha1
start, err := strconv.ParseInt(signCheck[0], 10, 64)
if err != nil {
return err
}
end, err := strconv.ParseInt(signCheck[1], 10, 64)
if err != nil {
return err
}
reader, err = file.RangeRead(http_range.Range{Start: start, Length: end - start + 1})
if err != nil {
return err
}
signVal, err := utils.HashReader(utils.SHA1, reader)
if err != nil {
return err
}
resp, err = d.client.UploadInit(ctx, &sdk.UploadInitReq{
FileName: file.GetName(),
FileSize: file.GetSize(),
Target: dstDir.GetID(),
FileID: strings.ToUpper(sha1),
PreID: strings.ToUpper(sha1128k),
SignKey: resp.SignKey,
SignVal: strings.ToUpper(signVal),
})
if err != nil {
return err
}
if resp.Status == 2 {
up(100)
return nil
}
}
// 3. get upload token
tokenResp, err := d.client.UploadGetToken(ctx)
if err != nil {
return err
}
// 4. upload
err = d.multpartUpload(ctx, file, up, tokenResp, resp)
if err != nil {
return err
}
return nil
}
func (d *Open115) OfflineDownload(ctx context.Context, uris []string, dstDir model.Obj) ([]string, error) {
return d.client.AddOfflineTaskURIs(ctx, uris, dstDir.GetID())
}
func (d *Open115) DeleteOfflineTask(ctx context.Context, infoHash string, deleteFiles bool) error {
return d.client.DeleteOfflineTask(ctx, infoHash, deleteFiles)
}
func (d *Open115) OfflineList(ctx context.Context) (*sdk.OfflineTaskListResp, error) {
resp, err := d.client.OfflineTaskList(ctx, 1)
if err != nil {
return nil, err
}
return resp, nil
}
func (d *Open115) GetDetails(ctx context.Context) (*model.StorageDetails, error) {
userInfo, err := d.client.UserInfo(ctx)
if err != nil {
return nil, err
}
total, err := ParseInt64(userInfo.RtSpaceInfo.AllTotal.Size)
if err != nil {
return nil, err
}
used, err := ParseInt64(userInfo.RtSpaceInfo.AllUse.Size)
if err != nil {
return nil, err
}
return &model.StorageDetails{
DiskUsage: model.DiskUsage{
TotalSpace: total,
UsedSpace: used,
},
}, nil
}
// func (d *Open115) GetArchiveMeta(ctx context.Context, obj model.Obj, args model.ArchiveArgs) (model.ArchiveMeta, error) {
// // TODO get archive file meta-info, return errs.NotImplement to use an internal archive tool, optional
// return nil, errs.NotImplement
// }
// func (d *Open115) ListArchive(ctx context.Context, obj model.Obj, args model.ArchiveInnerArgs) ([]model.Obj, error) {
// // TODO list args.InnerPath in the archive obj, return errs.NotImplement to use an internal archive tool, optional
// return nil, errs.NotImplement
// }
// func (d *Open115) Extract(ctx context.Context, obj model.Obj, args model.ArchiveInnerArgs) (*model.Link, error) {
// // TODO return link of file args.InnerPath in the archive obj, return errs.NotImplement to use an internal archive tool, optional
// return nil, errs.NotImplement
// }
// func (d *Open115) ArchiveDecompress(ctx context.Context, srcObj, dstDir model.Obj, args model.ArchiveDecompressArgs) ([]model.Obj, error) {
// // TODO extract args.InnerPath path in the archive srcObj to the dstDir location, optional
// // a folder with the same name as the archive file needs to be created to store the extracted results if args.PutIntoNewDir
// // return errs.NotImplement to use an internal archive tool
// return nil, errs.NotImplement
// }
//func (d *Template) Other(ctx context.Context, args model.OtherArgs) (interface{}, error) {
// return nil, errs.NotSupport
//}
var _ driver.Driver = (*Open115)(nil)
+30
View File
@@ -0,0 +1,30 @@
package _115_open
import (
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/op"
)
type Addition struct {
// Usually one of two
driver.RootID
// define other
OrderBy string `json:"order_by" type:"select" options:"file_name,file_size,user_utime,file_type"`
OrderDirection string `json:"order_direction" type:"select" options:"asc,desc"`
LimitRate float64 `json:"limit_rate" type:"float" default:"1" help:"limit all api request rate ([limit]r/1s)"`
PageSize int64 `json:"page_size" type:"number" default:"200" help:"list api per page size of 115open driver"`
AccessToken string `json:"access_token" required:"true"`
RefreshToken string `json:"refresh_token" required:"true"`
}
var config = driver.Config{
Name: "115 Open",
DefaultRoot: "0",
LinkCacheMode: driver.LinkCacheUA,
}
func init() {
op.RegisterDriver(func() driver.Driver {
return &Open115{}
})
}
+59
View File
@@ -0,0 +1,59 @@
package _115_open
import (
"time"
sdk "github.com/OpenListTeam/115-sdk-go"
"github.com/OpenListTeam/OpenList/v4/internal/model"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
)
type Obj sdk.GetFilesResp_File
// Thumb implements model.Thumb.
func (o *Obj) Thumb() string {
return o.Thumbnail
}
// CreateTime implements model.Obj.
func (o *Obj) CreateTime() time.Time {
return time.Unix(o.UpPt, 0)
}
// GetHash implements model.Obj.
func (o *Obj) GetHash() utils.HashInfo {
return utils.NewHashInfo(utils.SHA1, o.Sha1)
}
// GetID implements model.Obj.
func (o *Obj) GetID() string {
return o.Fid
}
// GetName implements model.Obj.
func (o *Obj) GetName() string {
return o.Fn
}
// GetPath implements model.Obj.
func (o *Obj) GetPath() string {
return ""
}
// GetSize implements model.Obj.
func (o *Obj) GetSize() int64 {
return o.FS
}
// IsDir implements model.Obj.
func (o *Obj) IsDir() bool {
return o.Fc == "0"
}
// ModTime implements model.Obj.
func (o *Obj) ModTime() time.Time {
return time.Unix(o.Upt, 0)
}
var _ model.Obj = (*Obj)(nil)
var _ model.Thumb = (*Obj)(nil)
+195
View File
@@ -0,0 +1,195 @@
package _115_open
import (
"context"
"encoding/base64"
"errors"
"io"
"time"
sdk "github.com/OpenListTeam/115-sdk-go"
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/model"
netutil "github.com/OpenListTeam/OpenList/v4/internal/net"
streamPkg "github.com/OpenListTeam/OpenList/v4/internal/stream"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
"github.com/avast/retry-go"
)
func calPartSize(fileSize int64) int64 {
var partSize int64 = 20 * utils.MB
if fileSize > partSize {
if fileSize > 1*utils.TB { // file Size over 1TB
partSize = 5 * utils.GB // file part size 5GB
} else if fileSize > 768*utils.GB { // over 768GB
partSize = 109951163 // ≈ 104.8576MB, split 1TB into 10,000 part
} else if fileSize > 512*utils.GB { // over 512GB
partSize = 82463373 // ≈ 78.6432MB
} else if fileSize > 384*utils.GB { // over 384GB
partSize = 54975582 // ≈ 52.4288MB
} else if fileSize > 256*utils.GB { // over 256GB
partSize = 41231687 // ≈ 39.3216MB
} else if fileSize > 128*utils.GB { // over 128GB
partSize = 27487791 // ≈ 26.2144MB
}
}
return partSize
}
func (d *Open115) singleUpload(ctx context.Context, tempF model.File, tokenResp *sdk.UploadGetTokenResp, initResp *sdk.UploadInitResp) error {
ossClient, err := netutil.NewOSSClient(tokenResp.Endpoint, tokenResp.AccessKeyId, tokenResp.AccessKeySecret, oss.SecurityToken(tokenResp.SecurityToken))
if err != nil {
return err
}
bucket, err := ossClient.Bucket(initResp.Bucket)
if err != nil {
return err
}
err = bucket.PutObject(initResp.Object, tempF,
oss.Callback(base64.StdEncoding.EncodeToString([]byte(initResp.Callback.Value.Callback))),
oss.CallbackVar(base64.StdEncoding.EncodeToString([]byte(initResp.Callback.Value.CallbackVar))),
)
return err
}
// type CallbackResult struct {
// State bool `json:"state"`
// Code int `json:"code"`
// Message string `json:"message"`
// Data struct {
// PickCode string `json:"pick_code"`
// FileName string `json:"file_name"`
// FileSize int64 `json:"file_size"`
// FileID string `json:"file_id"`
// ThumbURL string `json:"thumb_url"`
// Sha1 string `json:"sha1"`
// Aid int `json:"aid"`
// Cid string `json:"cid"`
// } `json:"data"`
// }
// retryExpiredToken retries only the rejected OSS operation, preserving the upload ID.
func retryExpiredToken(refresh func() error, operation func() error) error {
err := operation()
var serviceErr oss.ServiceError
if !errors.As(err, &serviceErr) || serviceErr.Code != "SecurityTokenExpired" {
return err
}
if err := refresh(); err != nil {
return err
}
return operation()
}
func (d *Open115) multpartUpload(ctx context.Context, stream model.FileStreamer, up driver.UpdateProgress, tokenResp *sdk.UploadGetTokenResp, initResp *sdk.UploadInitResp) error {
ossClient, err := netutil.NewOSSClient(tokenResp.Endpoint, tokenResp.AccessKeyId, tokenResp.AccessKeySecret, oss.SecurityToken(tokenResp.SecurityToken))
if err != nil {
return err
}
bucket, err := ossClient.Bucket(initResp.Bucket)
if err != nil {
return err
}
refresh := func() error {
if err := d.WaitLimit(ctx); err != nil {
return err
}
token, err := d.client.UploadGetToken(ctx)
if err != nil {
return err
}
client, err := netutil.NewOSSClient(token.Endpoint, token.AccessKeyId, token.AccessKeySecret, oss.SecurityToken(token.SecurityToken))
if err != nil {
return err
}
newBucket, err := client.Bucket(initResp.Bucket)
if err != nil {
return err
}
bucket = newBucket
return nil
}
var imur oss.InitiateMultipartUploadResult
err = retryExpiredToken(refresh, func() error {
var err error
imur, err = bucket.InitiateMultipartUpload(initResp.Object, oss.Sequential(), oss.WithContext(ctx))
return err
})
if err != nil {
return err
}
fileSize := stream.GetSize()
chunkSize := calPartSize(fileSize)
ss, err := streamPkg.NewStreamSectionReader(stream, int(chunkSize), &up)
if err != nil {
return err
}
partNum := (stream.GetSize() + chunkSize - 1) / chunkSize
parts := make([]oss.UploadPart, partNum)
offset := int64(0)
for i := int64(1); i <= partNum; i++ {
if utils.IsCanceled(ctx) {
return ctx.Err()
}
partSize := chunkSize
if i == partNum {
partSize = fileSize - (i-1)*chunkSize
}
rd, err := ss.GetSectionReader(offset, partSize)
if err != nil {
return err
}
err = retry.Do(func() error {
return retryExpiredToken(refresh, func() error {
if _, err := rd.Seek(0, io.SeekStart); err != nil {
return err
}
part, err := bucket.UploadPart(imur, driver.NewLimitedUploadStream(ctx, rd), partSize, int(i), oss.WithContext(ctx))
if err != nil {
return err
}
parts[i-1] = part
return nil
})
},
retry.Context(ctx),
retry.Attempts(3),
retry.DelayType(retry.BackOffDelay),
retry.Delay(time.Second))
ss.FreeSectionReader(rd)
if err != nil {
return err
}
if i == partNum {
offset = fileSize
} else {
offset += partSize
}
up(float64(offset) * 100 / float64(fileSize))
}
err = retryExpiredToken(refresh, func() error {
_, err := bucket.CompleteMultipartUpload(
imur,
parts,
oss.Callback(base64.StdEncoding.EncodeToString([]byte(initResp.Callback.Value.Callback))),
oss.CallbackVar(base64.StdEncoding.EncodeToString([]byte(initResp.Callback.Value.CallbackVar))),
oss.WithContext(ctx),
)
return err
})
if err != nil {
return err
}
return nil
}
+23
View File
@@ -0,0 +1,23 @@
package _115_open
import (
"encoding/json"
"strconv"
)
func ParseInt64(v json.Number) (int64, error) {
i, err := v.Int64()
if err == nil {
return i, nil
}
f, e1 := v.Float64()
if e1 == nil {
return int64(f), nil
}
return int64(0), err
}
func parseTime(value string) int64 {
timestamp, _ := strconv.ParseInt(value, 10, 64)
return timestamp
}
+26 -9
View File
@@ -2,12 +2,14 @@ package _115_share
import (
"context"
"net/http"
"github.com/OpenListTeam/OpenList/v4/drivers/base"
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/errs"
"github.com/OpenListTeam/OpenList/v4/internal/model"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
driver115 "github.com/SheltonZhu/115driver/pkg/driver"
"github.com/alist-org/alist/v3/internal/driver"
"github.com/alist-org/alist/v3/internal/errs"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/pkg/utils"
"golang.org/x/time/rate"
)
@@ -49,9 +51,16 @@ func (d *Pan115Share) List(ctx context.Context, dir model.Obj, args model.ListAr
if err := d.WaitLimit(ctx); err != nil {
return nil, err
}
var ua string
// TODO: will use user agent from header
// if args.Header != nil {
// ua = args.Header.Get("User-Agent")
// }
if ua == "" {
ua = base.UserAgentNT
}
files := make([]driver115.ShareFile, 0)
fileResp, err := d.client.GetShareSnap(d.ShareCode, d.ReceiveCode, dir.GetID(), driver115.QueryLimit(int(d.PageSize)))
fileResp, err := d.client.GetShareSnapWithUA(ua, d.ShareCode, d.ReceiveCode, dir.GetID(), driver115.QueryLimit(int(d.PageSize)))
if err != nil {
return nil, err
}
@@ -77,12 +86,20 @@ func (d *Pan115Share) Link(ctx context.Context, file model.Obj, args model.LinkA
if err := d.WaitLimit(ctx); err != nil {
return nil, err
}
downloadInfo, err := d.client.DownloadByShareCode(d.ShareCode, d.ReceiveCode, file.GetID())
var ua string
if args.Header != nil {
ua = args.Header.Get("User-Agent")
}
downloadInfo, err := d.client.DownloadByShareCodeWithUA(ua, d.ShareCode, d.ReceiveCode, file.GetID())
if err != nil {
return nil, err
}
return &model.Link{URL: downloadInfo.URL.URL}, nil
header := http.Header{}
header.Set("User-Agent", ua)
return &model.Link{
URL: downloadInfo.URL.URL,
Header: header,
}, nil
}
func (d *Pan115Share) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
+5 -10
View File
@@ -1,8 +1,8 @@
package _115_share
import (
"github.com/alist-org/alist/v3/internal/driver"
"github.com/alist-org/alist/v3/internal/op"
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/op"
)
type Addition struct {
@@ -10,7 +10,7 @@ type Addition struct {
QRCodeToken string `json:"qrcode_token" type:"text" help:"one of QR code token and cookie required"`
QRCodeSource string `json:"qrcode_source" type:"select" options:"web,android,ios,tv,alipaymini,wechatmini,qandroid" default:"linux" help:"select the QR code device, default linux"`
PageSize int64 `json:"page_size" type:"number" default:"1000" help:"list api per page size of 115 driver"`
LimitRate float64 `json:"limit_rate" type:"number" default:"2" help:"limit all api request rate (1r/[limit_rate]s)"`
LimitRate float64 `json:"limit_rate" type:"float" default:"2" help:"limit all api request rate (1r/[limit_rate]s)"`
ShareCode string `json:"share_code" type:"text" required:"true" help:"share code of 115 share link"`
ReceiveCode string `json:"receive_code" type:"text" required:"true" help:"receive code of 115 share link"`
driver.RootID
@@ -18,13 +18,8 @@ type Addition struct {
var config = driver.Config{
Name: "115 Share",
DefaultRoot: "",
// OnlyProxy: true,
// OnlyLocal: true,
CheckStatus: false,
Alert: "",
NoOverwriteUpload: true,
NoUpload: true,
DefaultRoot: "0",
NoUpload: true,
}
func init() {
+11 -6
View File
@@ -5,9 +5,10 @@ import (
"strconv"
"time"
"github.com/OpenListTeam/OpenList/v4/drivers/base"
"github.com/OpenListTeam/OpenList/v4/internal/model"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
driver115 "github.com/SheltonZhu/115driver/pkg/driver"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/pkg/errors"
)
@@ -20,6 +21,7 @@ type FileObj struct {
FileName string
isDir bool
FileID string
ThumbURL string
}
func (f *FileObj) CreateTime() time.Time {
@@ -54,6 +56,10 @@ func (f *FileObj) GetPath() string {
return ""
}
func (f *FileObj) Thumb() string {
return f.ThumbURL
}
func transFunc(sf driver115.ShareFile) (model.Obj, error) {
timeInt, err := strconv.ParseInt(sf.UpdateTime, 10, 64)
if err != nil {
@@ -74,15 +80,14 @@ func transFunc(sf driver115.ShareFile) (model.Obj, error) {
FileName: string(sf.FileName),
isDir: isDir,
FileID: fileID,
ThumbURL: sf.ThumbURL,
}, nil
}
var UserAgent = driver115.UA115Browser
func (d *Pan115Share) login() error {
var err error
opts := []driver115.Option{
driver115.UA(UserAgent),
driver115.UA(base.UserAgentNT),
}
d.client = driver115.New(opts...)
if _, err := d.client.GetShareSnap(d.ShareCode, d.ReceiveCode, ""); err != nil {
@@ -96,7 +101,7 @@ func (d *Pan115Share) login() error {
if cr, err = d.client.QRCodeLoginWithApp(s, driver115.LoginApp(d.QRCodeSource)); err != nil {
return errors.Wrap(err, "failed to login by qrcode")
}
d.Cookie = fmt.Sprintf("UID=%s;CID=%s;SEID=%s", cr.UID, cr.CID, cr.SEID)
d.Cookie = fmt.Sprintf("UID=%s;CID=%s;SEID=%s;KID=%s", cr.UID, cr.CID, cr.SEID, cr.KID)
d.QRCodeToken = ""
} else if d.Cookie != "" {
if err = cr.FromCookie(d.Cookie); err != nil {
+63 -59
View File
@@ -2,22 +2,22 @@ package _123
import (
"context"
"crypto/md5"
"encoding/base64"
"encoding/hex"
"fmt"
"golang.org/x/time/rate"
"io"
"net/http"
"net/url"
"strings"
"sync"
"time"
"github.com/alist-org/alist/v3/drivers/base"
"github.com/alist-org/alist/v3/internal/driver"
"github.com/alist-org/alist/v3/internal/errs"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/pkg/utils"
"golang.org/x/time/rate"
"github.com/OpenListTeam/OpenList/v4/drivers/base"
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/errs"
"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/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
@@ -41,12 +41,14 @@ func (d *Pan123) GetAddition() driver.Additional {
}
func (d *Pan123) Init(ctx context.Context) error {
_, err := d.request(UserInfo, http.MethodGet, nil, nil)
_, err := d.Request(UserInfo, http.MethodGet, func(req *resty.Request) {
req.SetHeader("platform", "web")
}, nil)
return err
}
func (d *Pan123) Drop(ctx context.Context) error {
_, _ = d.request(Logout, http.MethodPost, func(req *resty.Request) {
_, _ = d.Request(Logout, http.MethodPost, func(req *resty.Request) {
req.SetBody(base.Json{})
}, nil)
return nil
@@ -64,14 +66,6 @@ func (d *Pan123) List(ctx context.Context, dir model.Obj, args model.ListArgs) (
func (d *Pan123) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
if f, ok := file.(File); ok {
//var resp DownResp
var headers map[string]string
if !utils.IsLocalIPAddr(args.IP) {
headers = map[string]string{
//"X-Real-IP": "1.1.1.1",
"X-Forwarded-For": args.IP,
}
}
data := base.Json{
"driveId": 0,
"etag": f.Etag,
@@ -81,29 +75,30 @@ func (d *Pan123) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
"size": f.Size,
"type": f.Type,
}
resp, err := d.request(DownloadInfo, http.MethodPost, func(req *resty.Request) {
req.SetBody(data).SetHeaders(headers)
resp, err := d.Request(DownloadInfo, http.MethodPost, func(req *resty.Request) {
req.SetBody(data)
}, nil)
if err != nil {
return nil, err
}
downloadUrl := utils.Json.Get(resp, "data", "DownloadUrl").ToString()
u, err := url.Parse(downloadUrl)
ou, err := url.Parse(downloadUrl)
if err != nil {
return nil, err
}
nu := u.Query().Get("params")
u_ := ou.String()
nu := ou.Query().Get("params")
if nu != "" {
du, _ := base64.StdEncoding.DecodeString(nu)
u, err = url.Parse(string(du))
u, err := url.Parse(string(du))
if err != nil {
return nil, err
}
u_ = u.String()
}
u_ := u.String()
log.Debug("download url: ", u_)
res, err := base.NoRedirectClient.R().SetHeader("Referer", "https://www.123pan.com/").Get(u_)
res, err := base.NoRedirectClient.R().SetHeader("Referer", "https://yun.123pan.com/").Get(u_)
if err != nil {
return nil, err
}
@@ -118,7 +113,7 @@ func (d *Pan123) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
link.URL = utils.Json.Get(res.Body(), "data", "redirect_url").ToString()
}
link.Header = http.Header{
"Referer": []string{"https://www.123pan.com/"},
"Referer": []string{fmt.Sprintf("%s://%s/", ou.Scheme, ou.Host)},
}
return &link, nil
} else {
@@ -135,7 +130,7 @@ func (d *Pan123) MakeDir(ctx context.Context, parentDir model.Obj, dirName strin
"size": 0,
"type": 1,
}
_, err := d.request(Mkdir, http.MethodPost, func(req *resty.Request) {
_, err := d.Request(Mkdir, http.MethodPost, func(req *resty.Request) {
req.SetBody(data)
}, nil)
return err
@@ -146,7 +141,7 @@ func (d *Pan123) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
"fileIdList": []base.Json{{"FileId": srcObj.GetID()}},
"parentFileId": dstDir.GetID(),
}
_, err := d.request(Move, http.MethodPost, func(req *resty.Request) {
_, err := d.Request(Move, http.MethodPost, func(req *resty.Request) {
req.SetBody(data)
}, nil)
return err
@@ -158,7 +153,7 @@ func (d *Pan123) Rename(ctx context.Context, srcObj model.Obj, newName string) e
"fileId": srcObj.GetID(),
"fileName": newName,
}
_, err := d.request(Rename, http.MethodPost, func(req *resty.Request) {
_, err := d.Request(Rename, http.MethodPost, func(req *resty.Request) {
req.SetBody(data)
}, nil)
return err
@@ -175,7 +170,7 @@ func (d *Pan123) Remove(ctx context.Context, obj model.Obj) error {
"operation": true,
"fileTrashInfoList": []File{f},
}
_, err := d.request(Trash, http.MethodPost, func(req *resty.Request) {
_, err := d.Request(Trash, http.MethodPost, func(req *resty.Request) {
req.SetBody(data)
}, nil)
return err
@@ -184,36 +179,26 @@ func (d *Pan123) Remove(ctx context.Context, obj model.Obj) error {
}
}
func (d *Pan123) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
// const DEFAULT int64 = 10485760
h := md5.New()
// need to calculate md5 of the full content
tempFile, err := stream.CacheFullInTempFile()
if err != nil {
return err
func (d *Pan123) Put(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) error {
etag := file.GetHash().GetHash(utils.MD5)
var err error
if len(etag) < utils.MD5.Width {
_, etag, err = stream.CacheFullAndHash(file, &up, utils.MD5)
if err != nil {
return err
}
}
defer func() {
_ = tempFile.Close()
}()
if _, err = utils.CopyWithBuffer(h, tempFile); err != nil {
return err
}
_, err = tempFile.Seek(0, io.SeekStart)
if err != nil {
return err
}
etag := hex.EncodeToString(h.Sum(nil))
data := base.Json{
"driveId": 0,
"duplicate": 2, // 2->覆盖 1->重命名 0->默认
"etag": etag,
"fileName": stream.GetName(),
"etag": strings.ToLower(etag),
"fileName": file.GetName(),
"parentFileId": dstDir.GetID(),
"size": stream.GetSize(),
"size": file.GetSize(),
"type": 0,
}
var resp UploadResp
res, err := d.request(UploadRequest, http.MethodPost, func(req *resty.Request) {
res, err := d.Request(UploadRequest, http.MethodPost, func(req *resty.Request) {
req.SetBody(data).SetContext(ctx)
}, &resp)
if err != nil {
@@ -224,7 +209,7 @@ func (d *Pan123) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
return nil
}
if resp.Data.AccessKeyId == "" || resp.Data.SecretAccessKey == "" || resp.Data.SessionToken == "" {
err = d.newUpload(ctx, &resp, stream, tempFile, up)
err = d.newUpload(ctx, &resp, file, up)
return err
} else {
cfg := &aws.Config{
@@ -238,17 +223,23 @@ func (d *Pan123) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
return err
}
uploader := s3manager.NewUploader(s)
if stream.GetSize() > s3manager.MaxUploadParts*s3manager.DefaultUploadPartSize {
uploader.PartSize = stream.GetSize() / (s3manager.MaxUploadParts - 1)
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: tempFile,
Body: driver.NewLimitedUploadStream(ctx, &driver.ReaderUpdatingProgress{
Reader: file,
UpdateProgress: up,
}),
}
_, err = uploader.UploadWithContext(ctx, input)
if err != nil {
return err
}
}
_, err = d.request(UploadComplete, http.MethodPost, func(req *resty.Request) {
_, err = d.Request(UploadComplete, http.MethodPost, func(req *resty.Request) {
req.SetBody(base.Json{
"fileId": resp.Data.FileId,
}).SetContext(ctx)
@@ -264,4 +255,17 @@ func (d *Pan123) APIRateLimit(ctx context.Context, api string) error {
return limiter.Wait(ctx)
}
func (d *Pan123) GetDetails(ctx context.Context) (*model.StorageDetails, error) {
userInfo, err := d.getUserInfo(ctx)
if err != nil {
return nil, err
}
return &model.StorageDetails{
DiskUsage: model.DiskUsage{
TotalSpace: userInfo.Data.SpacePermanent + userInfo.Data.SpaceTemp,
UsedSpace: userInfo.Data.SpaceUsed,
},
}, nil
}
var _ driver.Driver = (*Pan123)(nil)
+13 -4
View File
@@ -1,8 +1,8 @@
package _123
import (
"github.com/alist-org/alist/v3/internal/driver"
"github.com/alist-org/alist/v3/internal/op"
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/op"
)
type Addition struct {
@@ -11,17 +11,26 @@ type Addition struct {
driver.RootID
//OrderBy string `json:"order_by" type:"select" options:"file_id,file_name,size,update_at" default:"file_name"`
//OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"`
AccessToken string
AccessToken string
UploadThread int `json:"UploadThread" type:"number" default:"3" help:"the threads of upload"`
Platform string `json:"platform" type:"string" default:"web" help:"the platform header value, sent with API requests"`
}
var config = driver.Config{
Name: "123Pan",
DefaultRoot: "0",
LocalSort: true,
PreferProxy: true,
}
func init() {
op.RegisterDriver(func() driver.Driver {
return &Pan123{}
// 新增默认选项 要在RegisterDriver初始化设置 才会对正在使用的用户生效
return &Pan123{
Addition: Addition{
UploadThread: 3,
Platform: "web",
},
}
})
}
+60 -3
View File
@@ -1,14 +1,15 @@
package _123
import (
"github.com/alist-org/alist/v3/pkg/utils"
"net/url"
"path"
"strconv"
"strings"
"time"
"github.com/alist-org/alist/v3/internal/model"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
"github.com/OpenListTeam/OpenList/v4/internal/model"
)
type File struct {
@@ -27,7 +28,7 @@ func (f File) CreateTime() time.Time {
}
func (f File) GetHash() utils.HashInfo {
return utils.HashInfo{}
return utils.NewHashInfo(utils.MD5, f.Etag)
}
func (f File) GetPath() string {
@@ -121,3 +122,59 @@ type S3PreSignedURLs struct {
PreSignedUrls map[string]string `json:"presignedUrls"`
} `json:"data"`
}
type UserInfoResp struct {
Data struct {
Uid int64 `json:"UID"`
Nickname string `json:"Nickname"`
SpaceUsed int64 `json:"SpaceUsed"`
SpacePermanent int64 `json:"SpacePermanent"`
SpaceTemp int64 `json:"SpaceTemp"`
FileCount int `json:"FileCount"`
} `json:"data"`
}
type offlineResolveResp struct {
Data struct {
List []struct {
Result int `json:"result"`
ID int64 `json:"id"`
ErrCode int `json:"err_code"`
ErrMsg string `json:"err_msg"`
Files []struct {
ID int64 `json:"id"`
} `json:"files"`
} `json:"list"`
} `json:"data"`
}
type offlineSubmitResp struct {
Data struct {
TaskList []struct {
TaskID int64 `json:"task_id"`
Result int `json:"result"`
} `json:"task_list"`
} `json:"data"`
}
type offlineTaskListResp struct {
Data struct {
HasRun bool `json:"has_run"`
List []offlineTask `json:"list"`
Total int `json:"total"`
} `json:"data"`
}
type offlineTask struct {
TaskID int64 `json:"task_id"`
Name string `json:"name"`
Status int `json:"status"`
Size int64 `json:"size"`
ThirdTask string `json:"third_task_id"`
Downloaded int64 `json:"downloaded"`
Progress float64 `json:"progress"`
UploadIDR int64 `json:"upload_idr"`
UploadName string `json:"upload_name"`
Type string `json:"type"`
Speed int64 `json:"speed"`
}
+102 -70
View File
@@ -4,14 +4,18 @@ import (
"context"
"fmt"
"io"
"math"
"net/http"
"strconv"
"time"
"github.com/alist-org/alist/v3/drivers/base"
"github.com/alist-org/alist/v3/internal/driver"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/OpenListTeam/OpenList/v4/drivers/base"
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/model"
"github.com/OpenListTeam/OpenList/v4/internal/stream"
"github.com/OpenListTeam/OpenList/v4/pkg/errgroup"
"github.com/OpenListTeam/OpenList/v4/pkg/singleflight"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
"github.com/avast/retry-go"
"github.com/go-resty/resty/v2"
)
@@ -25,7 +29,7 @@ func (d *Pan123) getS3PreSignedUrls(ctx context.Context, upReq *UploadResp, star
"StorageNode": upReq.Data.StorageNode,
}
var s3PreSignedUrls S3PreSignedURLs
_, err := d.request(S3PreSignedUrls, http.MethodPost, func(req *resty.Request) {
_, err := d.Request(S3PreSignedUrls, http.MethodPost, func(req *resty.Request) {
req.SetBody(data).SetContext(ctx)
}, &s3PreSignedUrls)
if err != nil {
@@ -44,7 +48,7 @@ func (d *Pan123) getS3Auth(ctx context.Context, upReq *UploadResp, start, end in
"uploadId": upReq.Data.UploadId,
}
var s3PreSignedUrls S3PreSignedURLs
_, err := d.request(S3Auth, http.MethodPost, func(req *resty.Request) {
_, err := d.Request(S3Auth, http.MethodPost, func(req *resty.Request) {
req.SetBody(data).SetContext(ctx)
}, &s3PreSignedUrls)
if err != nil {
@@ -63,93 +67,121 @@ func (d *Pan123) completeS3(ctx context.Context, upReq *UploadResp, file model.F
"key": upReq.Data.Key,
"uploadId": upReq.Data.UploadId,
}
_, err := d.request(UploadCompleteV2, http.MethodPost, func(req *resty.Request) {
_, err := d.Request(UploadCompleteV2, http.MethodPost, func(req *resty.Request) {
req.SetBody(data).SetContext(ctx)
}, nil)
return err
}
func (d *Pan123) newUpload(ctx context.Context, upReq *UploadResp, file model.FileStreamer, reader io.Reader, up driver.UpdateProgress) error {
chunkSize := int64(1024 * 1024 * 16)
func (d *Pan123) newUpload(ctx context.Context, upReq *UploadResp, file model.FileStreamer, up driver.UpdateProgress) error {
// fetch s3 pre signed urls
chunkCount := int(math.Ceil(float64(file.GetSize()) / float64(chunkSize)))
size := file.GetSize()
chunkSize := int64(16 * utils.MB)
chunkCount := 1
if size > chunkSize {
chunkCount = int((size + chunkSize - 1) / chunkSize)
}
ss, err := stream.NewStreamSectionReader(file, int(chunkSize), &up)
if err != nil {
return err
}
lastChunkSize := size % chunkSize
if lastChunkSize == 0 {
lastChunkSize = chunkSize
}
// only 1 batch is allowed
isMultipart := chunkCount > 1
batchSize := 1
getS3UploadUrl := d.getS3Auth
if isMultipart {
if chunkCount > 1 {
batchSize = 10
getS3UploadUrl = d.getS3PreSignedUrls
}
thread := min(int(chunkCount), d.UploadThread)
threadG, uploadCtx := errgroup.NewOrderedGroupWithContext(ctx, thread,
retry.Attempts(3),
retry.Delay(time.Second),
retry.DelayType(retry.BackOffDelay))
for i := 1; i <= chunkCount; i += batchSize {
if utils.IsCanceled(ctx) {
return ctx.Err()
if utils.IsCanceled(uploadCtx) {
break
}
start := i
end := i + batchSize
if end > chunkCount+1 {
end = chunkCount + 1
}
s3PreSignedUrls, err := getS3UploadUrl(ctx, upReq, start, end)
end := min(i+batchSize, chunkCount+1)
s3PreSignedUrls, err := getS3UploadUrl(uploadCtx, upReq, start, end)
if err != nil {
return err
}
// upload each chunk
for j := start; j < end; j++ {
if utils.IsCanceled(ctx) {
return ctx.Err()
for cur := start; cur < end; cur++ {
if utils.IsCanceled(uploadCtx) {
break
}
offset := int64(cur-1) * chunkSize
curSize := chunkSize
if j == chunkCount {
curSize = file.GetSize() - (int64(chunkCount)-1)*chunkSize
if cur == chunkCount {
curSize = lastChunkSize
}
err = d.uploadS3Chunk(ctx, upReq, s3PreSignedUrls, j, end, io.LimitReader(reader, chunkSize), curSize, false, getS3UploadUrl)
if err != nil {
return err
}
up(float64(j) * 100 / float64(chunkCount))
var reader io.ReadSeeker
threadG.GoWithLifecycle(errgroup.Lifecycle{
Before: func(ctx context.Context) (err error) {
reader, err = ss.GetSectionReader(offset, curSize)
return
},
Do: func(ctx context.Context) (err error) {
reader.Seek(0, io.SeekStart)
uploadUrl := s3PreSignedUrls.Data.PreSignedUrls[strconv.Itoa(cur)]
if uploadUrl == "" {
return fmt.Errorf("upload url is empty, s3PreSignedUrls: %+v", s3PreSignedUrls)
}
req, err := http.NewRequestWithContext(ctx, http.MethodPut, uploadUrl, driver.NewLimitedUploadStream(ctx, reader))
if err != nil {
return err
}
req.ContentLength = curSize
//req.Header.Set("Content-Length", strconv.FormatInt(curSize, 10))
res, err := base.HttpClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
if res.StatusCode == http.StatusForbidden {
_, err, _ = singleflight.AnyGroup.Do(fmt.Sprintf("Pan123.newUpload_%p", threadG), func() (any, error) {
newS3PreSignedUrls, err := getS3UploadUrl(ctx, upReq, cur, end)
if err != nil {
return nil, err
}
s3PreSignedUrls.Data.PreSignedUrls = newS3PreSignedUrls.Data.PreSignedUrls
return nil, nil
})
if err != nil {
return err
}
return fmt.Errorf("upload s3 chunk %d failed, status code: %d", cur, res.StatusCode)
}
if res.StatusCode != http.StatusOK {
body, err := io.ReadAll(res.Body)
if err != nil {
return err
}
return fmt.Errorf("upload s3 chunk %d failed, status code: %d, body: %s", cur, res.StatusCode, body)
}
progress := 100 * float64(threadG.Success()+1) / float64(chunkCount+1)
up(progress)
return nil
},
After: func(err error) {
ss.FreeSectionReader(reader)
},
})
}
}
if err := threadG.Wait(); err != nil {
return err
}
defer up(100)
// complete s3 upload
return d.completeS3(ctx, upReq, file, chunkCount > 1)
}
func (d *Pan123) uploadS3Chunk(ctx context.Context, upReq *UploadResp, s3PreSignedUrls *S3PreSignedURLs, cur, end int, reader io.Reader, curSize int64, retry bool, getS3UploadUrl func(ctx context.Context, upReq *UploadResp, start int, end int) (*S3PreSignedURLs, error)) error {
uploadUrl := s3PreSignedUrls.Data.PreSignedUrls[strconv.Itoa(cur)]
if uploadUrl == "" {
return fmt.Errorf("upload url is empty, s3PreSignedUrls: %+v", s3PreSignedUrls)
}
req, err := http.NewRequest("PUT", uploadUrl, reader)
if err != nil {
return err
}
req = req.WithContext(ctx)
req.ContentLength = curSize
//req.Header.Set("Content-Length", strconv.FormatInt(curSize, 10))
res, err := base.HttpClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
if res.StatusCode == http.StatusForbidden {
if retry {
return fmt.Errorf("upload s3 chunk %d failed, status code: %d", cur, res.StatusCode)
}
// refresh s3 pre signed urls
newS3PreSignedUrls, err := getS3UploadUrl(ctx, upReq, cur, end)
if err != nil {
return err
}
s3PreSignedUrls.Data.PreSignedUrls = newS3PreSignedUrls.Data.PreSignedUrls
// retry
return d.uploadS3Chunk(ctx, upReq, s3PreSignedUrls, cur, end, reader, curSize, true, getS3UploadUrl)
}
if res.StatusCode != http.StatusOK {
body, err := io.ReadAll(res.Body)
if err != nil {
return err
}
return fmt.Errorf("upload s3 chunk %d failed, status code: %d, body: %s", cur, res.StatusCode, body)
}
return nil
}
+148 -17
View File
@@ -13,8 +13,9 @@ import (
"strings"
"time"
"github.com/alist-org/alist/v3/drivers/base"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/OpenListTeam/OpenList/v4/drivers/base"
"github.com/OpenListTeam/OpenList/v4/internal/model"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
"github.com/go-resty/resty/v2"
jsoniter "github.com/json-iterator/go"
log "github.com/sirupsen/logrus"
@@ -23,9 +24,9 @@ import (
// do others that not defined in Driver interface
const (
Api = "https://www.123pan.com/api"
AApi = "https://www.123pan.com/a/api"
BApi = "https://www.123pan.com/b/api"
Api = "https://yun.123pan.com/api"
AApi = "https://yun.123pan.com/a/api"
BApi = "https://yun.123pan.com/b/api"
LoginApi = "https://login.123pan.com/api"
MainApi = BApi
SignIn = LoginApi + "/user/sign_in"
@@ -43,9 +44,16 @@ const (
S3Auth = MainApi + "/file/s3_upload_object/auth"
UploadCompleteV2 = MainApi + "/file/upload_complete/v2"
S3Complete = MainApi + "/file/s3_complete_multipart_upload"
//AuthKeySalt = "8-8D$sL8gPjom7bk#cY"
OfflineResolve = MainApi + "/v2/offline_download/task/resolve"
OfflineSubmit = MainApi + "/v2/offline_download/task/submit"
OfflineTaskList = MainApi + "/offline_download/task/list"
OfflineTaskDelete = MainApi + "/offline_download/task/delete"
// AuthKeySalt = "8-8D$sL8gPjom7bk#cY"
)
var ErrOfflineTaskNotFound = errors.New("offline task not found")
func signPath(path string, os string, version string) (k string, v string) {
table := []byte{'a', 'd', 'e', 'f', 'g', 'h', 'l', 'm', 'y', 'i', 'j', 'n', 'o', 'p', 'k', 'q', 'r', 's', 't', 'u', 'b', 'c', 'v', 'w', 's', 'z'}
random := fmt.Sprintf("%.f", math.Round(1e7*rand.Float64()))
@@ -161,9 +169,9 @@ func (d *Pan123) login() error {
}
res, err := base.RestyClient.R().
SetHeaders(map[string]string{
"origin": "https://www.123pan.com",
"referer": "https://www.123pan.com/",
"user-agent": "Dart/2.19(dart:io)-alist",
"origin": "https://yun.123pan.com",
"referer": "https://yun.123pan.com/",
"user-agent": "Dart/2.19(dart:io)-openlist",
"platform": "web",
"app-version": "3",
//"user-agent": base.UserAgent,
@@ -194,14 +202,16 @@ func (d *Pan123) login() error {
// return &authKey, nil
//}
func (d *Pan123) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
func (d *Pan123) Request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
isRetry := false
do:
req := base.RestyClient.R()
req.SetHeaders(map[string]string{
"origin": "https://www.123pan.com",
"referer": "https://www.123pan.com/",
"origin": "https://yun.123pan.com",
"referer": "https://yun.123pan.com/",
"authorization": "Bearer " + d.AccessToken,
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) alist-client",
"platform": "web",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) openlist-client",
"platform": d.Platform,
"app-version": "3",
//"user-agent": base.UserAgent,
})
@@ -223,18 +233,128 @@ func (d *Pan123) request(url string, method string, callback base.ReqCallback, r
body := res.Body()
code := utils.Json.Get(body, "code").ToInt()
if code != 0 {
if code == 401 {
if !isRetry && code == 401 {
err := d.login()
if err != nil {
return nil, err
}
return d.request(url, method, callback, resp)
isRetry = true
goto do
}
return nil, errors.New(jsoniter.Get(body, "message").ToString())
}
return body, nil
}
func (d *Pan123) OfflineDownload(ctx context.Context, uri string, dstDir model.Obj) (int64, error) {
var resolveResp offlineResolveResp
_, err := d.Request(OfflineResolve, http.MethodPost, func(req *resty.Request) {
req.SetContext(ctx).SetBody(base.Json{
"urls": uri,
})
}, &resolveResp)
if err != nil {
return 0, err
}
if len(resolveResp.Data.List) == 0 {
return 0, fmt.Errorf("offline resolve failed: empty response")
}
if resolveResp.Data.List[0].Result != 0 {
msg := resolveResp.Data.List[0].ErrMsg
if msg == "" {
msg = "offline resolve failed"
}
return 0, fmt.Errorf("%s", msg)
}
resourceID := resolveResp.Data.List[0].ID
if resourceID == 0 {
return 0, fmt.Errorf("offline resolve failed: empty resource id")
}
selectFileIDs := make([]int64, 0, len(resolveResp.Data.List[0].Files))
for _, f := range resolveResp.Data.List[0].Files {
if f.ID > 0 {
selectFileIDs = append(selectFileIDs, f.ID)
}
}
if len(selectFileIDs) == 0 {
return 0, fmt.Errorf("offline resolve failed: empty file list")
}
uploadDir, err := strconv.ParseInt(dstDir.GetID(), 10, 64)
if err != nil {
return 0, fmt.Errorf("invalid destination dir id: %s", dstDir.GetID())
}
var submitResp offlineSubmitResp
_, err = d.Request(OfflineSubmit, http.MethodPost, func(req *resty.Request) {
req.SetContext(ctx).SetBody(base.Json{
"resource_list": []base.Json{
{
"resource_id": resourceID,
"select_file_id": selectFileIDs,
},
},
"upload_dir": uploadDir,
})
}, &submitResp)
if err != nil {
return 0, err
}
if len(submitResp.Data.TaskList) == 0 {
return 0, fmt.Errorf("offline submit failed: empty task list")
}
if submitResp.Data.TaskList[0].Result != 0 {
return 0, fmt.Errorf("offline submit failed")
}
if submitResp.Data.TaskList[0].TaskID == 0 {
return 0, fmt.Errorf("offline submit failed: empty task id")
}
return submitResp.Data.TaskList[0].TaskID, nil
}
func (d *Pan123) GetOfflineTask(ctx context.Context, taskID int64) (*offlineTask, error) {
if taskID == 0 {
return nil, fmt.Errorf("invalid task id")
}
page := 1
pageSize := 100
statusArr := []int{0, 1, 2, 3}
for {
var listResp offlineTaskListResp
_, err := d.Request(OfflineTaskList, http.MethodPost, func(req *resty.Request) {
req.SetContext(ctx).SetBody(base.Json{
"current_page": page,
"page_size": pageSize,
"status_arr": statusArr,
})
}, &listResp)
if err != nil {
return nil, err
}
for i := range listResp.Data.List {
if listResp.Data.List[i].TaskID == taskID {
return &listResp.Data.List[i], nil
}
}
if len(listResp.Data.List) == 0 || page*pageSize >= listResp.Data.Total {
break
}
page++
}
return nil, ErrOfflineTaskNotFound
}
func (d *Pan123) DeleteOfflineTasks(ctx context.Context, taskIDs []int64) error {
if len(taskIDs) == 0 {
return nil
}
_, err := d.Request(OfflineTaskDelete, http.MethodPost, func(req *resty.Request) {
req.SetContext(ctx).SetBody(base.Json{
"task_ids": taskIDs,
})
}, nil)
return err
}
func (d *Pan123) getFiles(ctx context.Context, parentId string, name string) ([]File, error) {
page := 1
total := 0
@@ -260,7 +380,7 @@ func (d *Pan123) getFiles(ctx context.Context, parentId string, name string) ([]
"operateType": "4",
"inDirectSpace": "false",
}
_res, err := d.request(FileList, http.MethodGet, func(req *resty.Request) {
_res, err := d.Request(FileList, http.MethodGet, func(req *resty.Request) {
req.SetQueryParams(query)
}, &resp)
if err != nil {
@@ -279,3 +399,14 @@ func (d *Pan123) getFiles(ctx context.Context, parentId string, name string) ([]
}
return res, nil
}
func (d *Pan123) getUserInfo(ctx context.Context) (*UserInfoResp, error) {
var resp UserInfoResp
_, err := d.Request(UserInfo, http.MethodGet, func(req *resty.Request) {
req.SetContext(ctx)
}, &resp)
if err != nil {
return nil, err
}
return &resp, nil
}
+8 -4
View File
@@ -5,10 +5,10 @@ import (
stdpath "path"
"time"
"github.com/alist-org/alist/v3/internal/driver"
"github.com/alist-org/alist/v3/internal/errs"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/errs"
"github.com/OpenListTeam/OpenList/v4/internal/model"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
)
type Pan123Link struct {
@@ -39,6 +39,10 @@ func (d *Pan123Link) Drop(ctx context.Context) error {
return nil
}
func (Addition) GetRootPath() string {
return "/"
}
func (d *Pan123Link) Get(ctx context.Context, path string) (model.Obj, error) {
node := GetNodeFromRootByPath(d.root, path)
return nodeToObj(node, path)
+2 -2
View File
@@ -1,8 +1,8 @@
package _123Link
import (
"github.com/alist-org/alist/v3/internal/driver"
"github.com/alist-org/alist/v3/internal/op"
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/op"
)
type Addition struct {
+2 -2
View File
@@ -3,8 +3,8 @@ package _123Link
import (
"time"
"github.com/alist-org/alist/v3/internal/errs"
"github.com/alist-org/alist/v3/internal/model"
"github.com/OpenListTeam/OpenList/v4/internal/errs"
"github.com/OpenListTeam/OpenList/v4/internal/model"
)
// Node is a node in the folder tree
+276
View File
@@ -0,0 +1,276 @@
package _123_open
import (
"context"
"fmt"
"strconv"
"time"
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/errs"
"github.com/OpenListTeam/OpenList/v4/internal/model"
"github.com/OpenListTeam/OpenList/v4/internal/op"
"github.com/OpenListTeam/OpenList/v4/internal/stream"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
)
type Open123 struct {
model.Storage
Addition
UID uint64
tm *tokenManager
}
func (d *Open123) Config() driver.Config {
return config
}
func (d *Open123) GetAddition() driver.Additional {
return &d.Addition
}
func (d *Open123) Init(ctx context.Context) error {
if d.UploadThread < 1 || d.UploadThread > 32 {
d.UploadThread = 3
}
if (d.UseOnlineAPI && d.RefreshToken != "" && len(d.APIAddress) > 0) || (d.ClientID != "" && d.ClientSecret != "") {
// proactive refresh by renewapi or client credentials
d.AccessToken = ""
d.tm = &tokenManager{}
} else {
// 避免个人 token 刷新产生的多个登录,被动刷新
// 默认过期时间90天,jwt exp 不可靠
d.tm = &tokenManager{
// accessToken: d.AccessToken,
expiredAt: time.Now().Add(90 * 24 * time.Hour),
}
}
_, err := d.getAccessToken(false)
if err != nil {
return fmt.Errorf("init get access token error: %w", err)
}
return nil
}
func (d *Open123) Drop(ctx context.Context) error {
op.MustSaveDriverStorage(d)
return nil
}
func (d *Open123) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
fileLastId := int64(0)
parentFileId, err := strconv.ParseInt(dir.GetID(), 10, 64)
if err != nil {
return nil, err
}
res := make([]File, 0)
for fileLastId != -1 {
files, err := d.getFiles(parentFileId, 100, fileLastId)
if err != nil {
return nil, err
}
// 目前123panAPI请求,trashed失效,只能通过遍历过滤
for i := range files.Data.FileList {
if files.Data.FileList[i].Trashed == 0 {
res = append(res, files.Data.FileList[i])
}
}
fileLastId = files.Data.LastFileId
}
return utils.SliceConvert(res, func(src File) (model.Obj, error) {
return src, nil
})
}
func (d *Open123) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
fileId, _ := strconv.ParseInt(file.GetID(), 10, 64)
if d.DirectLink {
res, err := d.getDirectLink(fileId)
if err != nil {
return nil, err
}
if d.DirectLinkPrivateKey == "" {
duration := 365 * 24 * time.Hour // 缓存1年
return &model.Link{
URL: res.Data.URL,
Expiration: &duration,
}, nil
}
uid, err := d.getUID(ctx)
if err != nil {
return nil, err
}
duration := time.Duration(d.DirectLinkValidDuration) * time.Minute
newURL, err := d.SignURL(res.Data.URL, d.DirectLinkPrivateKey,
uid, duration)
if err != nil {
return nil, err
}
return &model.Link{
URL: newURL,
Expiration: &duration,
}, nil
}
res, err := d.getDownloadInfo(fileId)
if err != nil {
return nil, err
}
return &model.Link{URL: res.Data.DownloadUrl}, nil
}
func (d *Open123) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
parentFileId, _ := strconv.ParseInt(parentDir.GetID(), 10, 64)
return d.mkdir(parentFileId, dirName)
}
func (d *Open123) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
toParentFileID, _ := strconv.ParseInt(dstDir.GetID(), 10, 64)
return d.move(srcObj.(File).FileId, toParentFileID)
}
func (d *Open123) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
fileId, _ := strconv.ParseInt(srcObj.GetID(), 10, 64)
return d.rename(fileId, newName)
}
func (d *Open123) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
// 尝试使用上传+MD5秒传功能实现复制
// 1. 创建文件
// parentFileID 父目录id,上传到根目录时填写 0
parentFileId, err := strconv.ParseInt(dstDir.GetID(), 10, 64)
if err != nil {
return fmt.Errorf("parse parentFileID error: %v", err)
}
etag := srcObj.(File).Etag
createResp, err := d.create(parentFileId, srcObj.GetName(), etag, srcObj.GetSize(), 2, false)
if err != nil {
return err
}
// 是否秒传
if createResp.Data.Reuse {
return nil
}
return errs.NotSupport
}
func (d *Open123) Remove(ctx context.Context, obj model.Obj) error {
fileId, _ := strconv.ParseInt(obj.GetID(), 10, 64)
return d.trash(fileId)
}
func (d *Open123) Put(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) (model.Obj, error) {
// 1. 创建文件
// parentFileID 父目录id,上传到根目录时填写 0
parentFileId, err := strconv.ParseInt(dstDir.GetID(), 10, 64)
if err != nil {
return nil, fmt.Errorf("parse parentFileID error: %v", err)
}
// 尝试 SHA1 秒传
sha1Hash := file.GetHash().GetHash(utils.SHA1)
if len(sha1Hash) == utils.SHA1.Width {
resp, err := d.sha1Reuse(parentFileId, file.GetName(), sha1Hash, file.GetSize(), 2)
if err == nil && resp.Data.Reuse {
return File{
FileName: file.GetName(),
Size: file.GetSize(),
FileId: resp.Data.FileID,
Type: 2,
SHA1: sha1Hash,
}, nil
}
}
// etag 文件md5
etag := file.GetHash().GetHash(utils.MD5)
if len(etag) < utils.MD5.Width {
_, etag, err = stream.CacheFullAndHash(file, &up, utils.MD5)
if err != nil {
return nil, err
}
}
createResp, err := d.create(parentFileId, file.GetName(), etag, file.GetSize(), 2, false)
if err != nil {
return nil, err
}
// 是否秒传
if createResp.Data.Reuse {
// 秒传成功才会返回正确的 FileID,否则为 0
if createResp.Data.FileID != 0 {
return File{
FileName: file.GetName(),
Size: file.GetSize(),
FileId: createResp.Data.FileID,
Type: 2,
Etag: etag,
}, nil
}
}
// 2. 上传分片
err = d.Upload(ctx, file, createResp, up)
if err != nil {
return nil, err
}
// 3. 上传完毕
for range 60 {
uploadCompleteResp, err := d.complete(createResp.Data.PreuploadID)
// 返回错误代码未知,如:20103,文档也没有具体说
if err == nil && uploadCompleteResp.Data.Completed && uploadCompleteResp.Data.FileID != 0 {
up(100)
return File{
FileName: file.GetName(),
Size: file.GetSize(),
FileId: uploadCompleteResp.Data.FileID,
Type: 2,
Etag: etag,
}, nil
}
// 若接口返回的completed为 false 时,则需间隔1秒继续轮询此接口,获取上传最终结果。
time.Sleep(time.Second)
}
return nil, fmt.Errorf("upload complete timeout")
}
func (d *Open123) GetDetails(ctx context.Context) (*model.StorageDetails, error) {
userInfo, err := d.getUserInfo(ctx)
if err != nil {
return nil, err
}
return &model.StorageDetails{
DiskUsage: model.DiskUsage{
TotalSpace: userInfo.Data.SpacePermanent + userInfo.Data.SpaceTemp,
UsedSpace: userInfo.Data.SpaceUsed,
},
}, nil
}
func (d *Open123) OfflineDownload(ctx context.Context, url string, dir model.Obj, callback string) (int, error) {
return d.createOfflineDownloadTask(ctx, url, dir.GetID(), callback)
}
func (d *Open123) OfflineDownloadProcess(ctx context.Context, taskID int) (float64, int, error) {
return d.queryOfflineDownloadStatus(ctx, taskID)
}
var (
_ driver.Driver = (*Open123)(nil)
_ driver.PutResult = (*Open123)(nil)
)
+49
View File
@@ -0,0 +1,49 @@
package _123_open
import (
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/op"
)
type Addition struct {
// 通过 https://www.123pan.com/developer 申请
ClientID string `json:"ClientID" required:"false"`
ClientSecret string `json:"ClientSecret" required:"false"`
// 直接写入AccessToken, AccessToken有过期时间,不建议直接填写
AccessToken string `json:"AccessToken" required:"false"`
// refresh_token方式的AccessToken 【对个人开发者暂未开放】
RefreshToken string `json:"RefreshToken" required:"false"`
// 使用在线API
UseOnlineAPI bool `json:"use_online_api" default:"true"`
APIAddress string `json:"api_url_address" default:"https://api.oplist.org/123cloud/renewapi"`
// 用户名+密码方式登录的AccessToken可以兼容
//Username string `json:"username" required:"false"`
//Password string `json:"password" required:"false"`
// 上传线程数
UploadThread int `json:"UploadThread" type:"number" default:"3" help:"the threads of upload"`
// 使用直链
DirectLink bool `json:"DirectLink" type:"bool" default:"false" required:"false" help:"use direct link when download file"`
DirectLinkPrivateKey string `json:"DirectLinkPrivateKey" required:"false" help:"private key for direct link, if URL authentication is enabled"`
DirectLinkValidDuration int64 `json:"DirectLinkValidDuration" type:"number" default:"30" required:"false" help:"minutes, if URL authentication is enabled"`
driver.RootID
}
var config = driver.Config{
Name: "123 Open",
DefaultRoot: "0",
LocalSort: true,
PreferProxy: true,
}
func init() {
op.RegisterDriver(func() driver.Driver {
return &Open123{}
})
}
+129
View File
@@ -0,0 +1,129 @@
package _123_open
import (
"errors"
"fmt"
"net/http"
"sync"
"time"
"github.com/OpenListTeam/OpenList/v4/drivers/base"
"github.com/OpenListTeam/OpenList/v4/internal/op"
)
var (
AccessToken = "https://open-api.123pan.com/api/v1/access_token"
)
func expiresInToExpiredAt(expiresIn int64) (time.Time, error) {
if expiresIn <= 0 {
return time.Time{}, errors.New("invalid expires_in from official API")
}
return time.Now().UTC().Add(time.Duration(expiresIn) * time.Second), nil
}
type tokenManager struct {
// accessToken string
expiredAt time.Time
mu sync.Mutex
blockRefresh bool
}
func (d *Open123) getAccessToken(forceRefresh bool) (string, error) {
tm := d.tm
tm.mu.Lock()
defer tm.mu.Unlock()
if tm.blockRefresh {
return "", errors.New("Authentication expired")
}
if !forceRefresh && d.AccessToken != "" && time.Now().Before(tm.expiredAt.Add(-5*time.Minute)) {
return d.AccessToken, nil
}
if err := d.flushAccessToken(); err != nil {
// token expired and failed to refresh, block further refresh attempts
tm.blockRefresh = true
return "", err
}
return d.AccessToken, nil
}
func (d *Open123) flushAccessToken() error {
// Official app renewapi response contains access_token, refresh_token and expires_in.
if d.UseOnlineAPI && d.RefreshToken != "" && len(d.APIAddress) > 0 {
var resp RefreshTokenResp
_, err := base.RestyClient.R().
SetResult(&resp).
SetQueryParams(map[string]string{
"refresh_ui": d.RefreshToken,
"server_use": "true",
"driver_txt": "123cloud_oa",
}).
Get(d.APIAddress)
if err != nil {
return err
}
if resp.AccessToken == "" || resp.RefreshToken == "" {
errMessage := resp.ErrorDescription
if errMessage == "" {
errMessage = resp.Text
}
if errMessage == "" {
errMessage = resp.Message
}
if errMessage == "" {
errMessage = resp.Error
}
if errMessage != "" {
return fmt.Errorf("failed to refresh token: %s", errMessage)
}
return fmt.Errorf("empty access_token or refresh_token returned from official API")
}
expiredAt, err := expiresInToExpiredAt(resp.ExpiresIn)
if err != nil {
return err
}
d.AccessToken = resp.AccessToken
d.RefreshToken = resp.RefreshToken
d.tm.expiredAt = expiredAt
op.MustSaveDriverStorage(d)
d.tm.blockRefresh = false
return nil
}
// Developer API response contains code/message/data(accessToken, expiredAt).
if d.ClientID != "" && d.ClientSecret != "" {
req := base.RestyClient.R()
req.SetHeaders(map[string]string{
"platform": "open_platform",
"Content-Type": "application/json",
})
var resp AccessTokenResp
req.SetBody(base.Json{
"clientID": d.ClientID,
"clientSecret": d.ClientSecret,
})
req.SetResult(&resp)
_, err := req.Execute(http.MethodPost, AccessToken)
if err != nil {
return err
}
if resp.Code != 0 {
return fmt.Errorf("get access token failed: %s", resp.Message)
}
if resp.Data.AccessToken == "" || resp.Data.ExpiredAt == "" {
return errors.New("invalid token payload from developer API")
}
expiredAt, err := time.Parse(time.RFC3339, resp.Data.ExpiredAt)
if err != nil {
return fmt.Errorf("parse expire time failed: %w", err)
}
d.AccessToken = resp.Data.AccessToken
d.tm.expiredAt = expiredAt.UTC()
op.MustSaveDriverStorage(d)
d.tm.blockRefresh = false
return nil
}
return errors.New("no valid authentication method available")
}
+221
View File
@@ -0,0 +1,221 @@
package _123_open
import (
"strconv"
"time"
"github.com/OpenListTeam/OpenList/v4/internal/model"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
)
type ApiInfo struct {
url string
qps int
token chan struct{}
}
func (a *ApiInfo) Require() {
if a.qps > 0 {
a.token <- struct{}{}
}
}
func (a *ApiInfo) Release() {
if a.qps > 0 {
time.AfterFunc(time.Second, func() {
<-a.token
})
}
}
func (a *ApiInfo) SetQPS(qps int) {
a.qps = qps
a.token = make(chan struct{}, qps)
}
func (a *ApiInfo) NowLen() int {
return len(a.token)
}
func InitApiInfo(url string, qps int) *ApiInfo {
return &ApiInfo{
url: url,
qps: qps,
token: make(chan struct{}, qps),
}
}
type File struct {
FileName string `json:"filename"`
Size int64 `json:"size"`
CreateAt string `json:"createAt"`
UpdateAt string `json:"updateAt"`
FileId int64 `json:"fileId"`
Type int `json:"type"`
Etag string `json:"etag"`
S3KeyFlag string `json:"s3KeyFlag"`
ParentFileId int `json:"parentFileId"`
Category int `json:"category"`
Status int `json:"status"`
Trashed int `json:"trashed"`
SHA1 string
}
func (f File) GetHash() utils.HashInfo {
if len(f.SHA1) == utils.SHA1.Width && len(f.Etag) != utils.MD5.Width {
return utils.NewHashInfo(utils.SHA1, f.SHA1)
}
return utils.NewHashInfo(utils.MD5, f.Etag)
}
func (f File) GetPath() string {
return ""
}
func (f File) GetSize() int64 {
return f.Size
}
func (f File) GetName() string {
return f.FileName
}
func (f File) CreateTime() time.Time {
// 返回的时间没有时区信息,默认 UTC+8
loc := time.FixedZone("UTC+8", 8*60*60)
parsedTime, err := time.ParseInLocation("2006-01-02 15:04:05", f.CreateAt, loc)
if err != nil {
return time.Now()
}
return parsedTime
}
func (f File) ModTime() time.Time {
// 返回的时间没有时区信息,默认 UTC+8
loc := time.FixedZone("UTC+8", 8*60*60)
parsedTime, err := time.ParseInLocation("2006-01-02 15:04:05", f.UpdateAt, loc)
if err != nil {
return time.Now()
}
return parsedTime
}
func (f File) IsDir() bool {
return f.Type == 1
}
func (f File) GetID() string {
return strconv.FormatInt(f.FileId, 10)
}
var _ model.Obj = (*File)(nil)
type BaseResp struct {
Code int `json:"code"`
Message string `json:"message"`
XTraceID string `json:"x-traceID"`
}
type AccessTokenResp struct {
BaseResp
Data struct {
AccessToken string `json:"accessToken"`
ExpiredAt string `json:"expiredAt"`
} `json:"data"`
}
type RefreshTokenResp struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int64 `json:"expires_in"`
Code int `json:"code"`
Message string `json:"message"`
ErrorDescription string `json:"error_description"`
Error string `json:"error"`
Text string `json:"text"`
}
type UserInfoResp struct {
BaseResp
Data struct {
UID uint64 `json:"uid"`
// Username string `json:"username"`
// DisplayName string `json:"displayName"`
// HeadImage string `json:"headImage"`
// Passport string `json:"passport"`
// Mail string `json:"mail"`
SpaceUsed int64 `json:"spaceUsed"`
SpacePermanent int64 `json:"spacePermanent"`
SpaceTemp int64 `json:"spaceTemp"`
// SpaceTempExpr int64 `json:"spaceTempExpr"`
// Vip bool `json:"vip"`
// DirectTraffic int64 `json:"directTraffic"`
// IsHideUID bool `json:"isHideUID"`
} `json:"data"`
}
type FileListResp struct {
BaseResp
Data struct {
LastFileId int64 `json:"lastFileId"`
FileList []File `json:"fileList"`
} `json:"data"`
}
type DownloadInfoResp struct {
BaseResp
Data struct {
DownloadUrl string `json:"downloadUrl"`
} `json:"data"`
}
type DirectLinkResp struct {
BaseResp
Data struct {
URL string `json:"url"`
} `json:"data"`
}
// 创建文件V2返回
type UploadCreateResp struct {
BaseResp
Data struct {
FileID int64 `json:"fileID"`
PreuploadID string `json:"preuploadID"`
Reuse bool `json:"reuse"`
SliceSize int64 `json:"sliceSize"`
Servers []string `json:"servers"`
} `json:"data"`
}
// 上传完毕V2返回
type UploadCompleteResp struct {
BaseResp
Data struct {
Completed bool `json:"completed"`
FileID int64 `json:"fileID"`
} `json:"data"`
}
type SHA1ReuseResp struct {
BaseResp
Data struct {
FileID int64 `json:"fileID"`
Reuse bool `json:"reuse"`
} `json:"data"`
}
type OfflineDownloadResp struct {
BaseResp
Data struct {
TaskID int `json:"taskID"`
} `json:"data"`
}
type OfflineDownloadProcessResp struct {
BaseResp
Data struct {
Process float64 `json:"process"`
Status int `json:"status"`
} `json:"data"`
}
+203
View File
@@ -0,0 +1,203 @@
package _123_open
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"strconv"
"strings"
"time"
"github.com/OpenListTeam/OpenList/v4/drivers/base"
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/model"
"github.com/OpenListTeam/OpenList/v4/internal/stream"
"github.com/OpenListTeam/OpenList/v4/pkg/errgroup"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
"github.com/avast/retry-go"
"github.com/go-resty/resty/v2"
)
// 创建文件 V2
func (d *Open123) create(parentFileID int64, filename string, etag string, size int64, duplicate int, containDir bool) (*UploadCreateResp, error) {
var resp UploadCreateResp
_, err := d.Request(UploadCreate, http.MethodPost, func(req *resty.Request) {
req.SetBody(base.Json{
"parentFileId": parentFileID,
"filename": filename,
"etag": strings.ToLower(etag),
"size": size,
"duplicate": duplicate,
"containDir": containDir,
})
}, &resp)
if err != nil {
return nil, err
}
return &resp, nil
}
// 上传分片 V2
func (d *Open123) Upload(ctx context.Context, file model.FileStreamer, createResp *UploadCreateResp, up driver.UpdateProgress) error {
uploadDomain := createResp.Data.Servers[0]
size := file.GetSize()
chunkSize := createResp.Data.SliceSize
ss, err := stream.NewStreamSectionReader(file, int(chunkSize), &up)
if err != nil {
return err
}
uploadNums := (size + chunkSize - 1) / chunkSize
thread := min(int(uploadNums), d.UploadThread)
threadG, uploadCtx := errgroup.NewOrderedGroupWithContext(ctx, thread,
retry.Attempts(3),
retry.Delay(time.Second),
retry.DelayType(retry.BackOffDelay))
for partIndex := range uploadNums {
if utils.IsCanceled(uploadCtx) {
break
}
partIndex := partIndex
partNumber := partIndex + 1 // 分片号从1开始
offset := partIndex * chunkSize
size := min(chunkSize, size-offset)
var reader io.ReadSeeker
var rateLimitedRd io.Reader
sliceMD5 := ""
// 表单
b := bytes.NewBuffer(make([]byte, 0, 2048))
threadG.GoWithLifecycle(errgroup.Lifecycle{
Before: func(ctx context.Context) (err error) {
reader, err = ss.GetSectionReader(offset, size)
return
},
Do: func(ctx context.Context) (err error) {
reader.Seek(0, io.SeekStart)
if sliceMD5 == "" {
// 把耗时的计算放在这里,避免阻塞其他协程
sliceMD5, err = utils.HashReader(utils.MD5, reader)
if err != nil {
return err
}
reader.Seek(0, io.SeekStart)
}
b.Reset()
w := multipart.NewWriter(b)
// 添加表单字段
err = w.WriteField("preuploadID", createResp.Data.PreuploadID)
if err != nil {
return err
}
err = w.WriteField("sliceNo", strconv.FormatInt(partNumber, 10))
if err != nil {
return err
}
err = w.WriteField("sliceMD5", sliceMD5)
if err != nil {
return err
}
// 写入文件内容
_, err = w.CreateFormFile("slice", fmt.Sprintf("%s.part%d", file.GetName(), partNumber))
if err != nil {
return err
}
headSize := b.Len()
err = w.Close()
if err != nil {
return err
}
head := bytes.NewReader(b.Bytes()[:headSize])
tail := bytes.NewReader(b.Bytes()[headSize:])
rateLimitedRd = driver.NewLimitedUploadStream(ctx, io.MultiReader(head, reader, tail))
token, err := d.getAccessToken(false)
if err != nil {
return err
}
// 创建请求并设置header
req, err := http.NewRequestWithContext(ctx, http.MethodPost, uploadDomain+"/upload/v2/file/slice", rateLimitedRd)
if err != nil {
return err
}
// 设置请求头
req.Header.Add("Authorization", "Bearer "+token)
req.Header.Add("Content-Type", w.FormDataContentType())
req.Header.Add("Platform", "open_platform")
res, err := base.HttpClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
if res.StatusCode != 200 {
return fmt.Errorf("slice %d upload failed, status code: %d", partNumber, res.StatusCode)
}
b.Reset()
_, err = b.ReadFrom(res.Body)
if err != nil {
return err
}
var resp BaseResp
err = json.Unmarshal(b.Bytes(), &resp)
if err != nil {
return err
}
if resp.Code != 0 {
return fmt.Errorf("slice %d upload failed: %s", partNumber, resp.Message)
}
progress := 100 * float64(threadG.Success()+1) / float64(uploadNums+1)
up(progress)
return nil
},
After: func(err error) {
ss.FreeSectionReader(reader)
},
})
}
if err := threadG.Wait(); err != nil {
return err
}
return nil
}
// 上传完毕
func (d *Open123) complete(preuploadID string) (*UploadCompleteResp, error) {
var resp UploadCompleteResp
_, err := d.Request(UploadComplete, http.MethodPost, func(req *resty.Request) {
req.SetBody(base.Json{
"preuploadID": preuploadID,
})
}, &resp)
if err != nil {
return nil, err
}
return &resp, nil
}
// SHA1 秒传
func (d *Open123) sha1Reuse(parentFileID int64, filename string, sha1Hash string, size int64, duplicate int) (*SHA1ReuseResp, error) {
var resp SHA1ReuseResp
_, err := d.Request(UploadSHA1Reuse, http.MethodPost, func(req *resty.Request) {
req.SetBody(base.Json{
"parentFileID": parentFileID,
"filename": filename,
"sha1": strings.ToLower(sha1Hash),
"size": size,
"duplicate": duplicate,
})
}, &resp)
if err != nil {
return nil, err
}
return &resp, nil
}

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