feat(drivers/alidoc): add DingTalk Docs driver#2543
Conversation
Generated with OpenAI Codex
Generated with OpenAI Codex
Generated with OpenAI Codex
Generated with OpenAI Codex
jyxjjj
left a comment
There was a problem hiding this comment.
请不要随意篡改PR模板
请撤回gitignore的改动
请仔细阅读Git官方文档有关如何仅在本地忽略内容而无需将忽略行为推送至仓库的部分
已撤回gitignore的改动 |
Generated with OpenAI Codex
Generated with OpenAI Codex
Generated with OpenAI Codex
| Alert: "info|This driver supports accessing DingDrive through DingTalk Docs, including listing, download, upload, move, and recycle delete.", | ||
| } |
|
@zjhcx 麻烦增加文档到OpenList-Docs,前端的翻译可以不用管,会自动生成 |
我在写文档 |
已添加文档 |
| parentPath := "/" | ||
| if dir != nil { | ||
| if id := strings.TrimSpace(dir.GetID()); id != "" { | ||
| parentID = id | ||
| } | ||
| if p := dir.GetPath(); p != "" { | ||
| parentPath = p | ||
| } | ||
| } |
| func (d *AliDoc) findUploadedObj(ctx context.Context, parentID, parentPath, name string, size int64, startedAt time.Time) (model.Obj, error) { | ||
| for attempt := 0; attempt < 5; attempt++ { | ||
| items, err := d.list(ctx, parentID) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| var ( | ||
| matched dentry | ||
| hasMatched bool | ||
| ) | ||
| for i := range items { | ||
| item := items[i] | ||
| if item.DentryType != "file" || item.Name != name { | ||
| continue | ||
| } | ||
| if size >= 0 && item.FileSize != size { | ||
| continue | ||
| } | ||
| if !hasMatched || item.UpdatedTime > matched.UpdatedTime { | ||
| matched = item | ||
| hasMatched = true | ||
| } | ||
| } | ||
| if hasMatched { | ||
| obj := toObj(parentPath, matched) | ||
| if !obj.ModTime().IsZero() && obj.ModTime().Before(startedAt.Add(-5*time.Second)) { | ||
| // Keep polling briefly if only an older homonymous file is visible. | ||
| } else { | ||
| return obj, nil | ||
| } | ||
| } | ||
| if attempt < 4 { | ||
| timer := time.NewTimer(time.Duration(attempt+1) * 300 * time.Millisecond) | ||
| select { | ||
| case <-ctx.Done(): | ||
| timer.Stop() | ||
| return nil, ctx.Err() | ||
| case <-timer.C: | ||
| } | ||
| } | ||
| } | ||
| return nil, fmt.Errorf("uploaded object not found") | ||
| } |
There was a problem hiding this comment.
这个也建议删掉,如果文件上传api没返回 文件信息,可以直接返回nil,
| return src, size, nil | ||
| } | ||
|
|
||
| src, err := file.CacheFullAndWriter(nil, nil) |
Generated with OpenAI Codex
Generated with OpenAI Codex
| func prepareAliDocUploadFile(file model.FileStreamer) (model.File, error) { | ||
| if src := file.GetFile(); src != nil { | ||
| if _, err := src.Seek(0, io.SeekStart); err != nil { | ||
| return nil, err | ||
| } | ||
| return src, nil | ||
| } | ||
|
|
||
| src, err := file.CacheFullAndWriter(nil, nil) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| if _, err := src.Seek(0, io.SeekStart); err != nil { | ||
| return nil, err | ||
| } | ||
| return src, nil | ||
| } |
There was a problem hiding this comment.
这个删掉,传file给multipartUpload,在multipartUpload使用stream.NewStreamSectionReader顺序读取分片,参考
单线程分片上传 stream.NewStreamSectionReader + retry.Do
OpenList/drivers/google_drive/util.go
Lines 335 to 397 in 9b587ee
多线程分片上传 stream.NewStreamSectionReader + errgroup.NewOrderedGroupWithContext
OpenList/drivers/123/upload.go
Lines 76 to 187 in 9b587ee
| var uploadErr error | ||
| var reader io.ReadSeeker | ||
| for attempt := 0; attempt < 3; attempt++ { | ||
| reader, uploadErr = ss.GetSectionReader(offset, length) |
Generated with OpenAI Codex
Co-authored-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com> Signed-off-by: Unity_exe <zjhcx12@gmail.com>
|
其他的代码也简化一下,只要确保List返回的Obj正确即可,其他的方法就不要写过多的判断逻辑了 |
| return &Object{ | ||
| Object: model.Object{ | ||
| Name: srcObj.GetName(), | ||
| Size: srcObj.GetSize(), | ||
| Modified: srcObj.ModTime(), | ||
| Ctime: srcObj.CreateTime(), | ||
| IsFolder: srcObj.IsDir(), | ||
| HashInfo: srcObj.GetHash(), | ||
| }, | ||
| DentryType: pickAliDocDentryType(srcObj), | ||
| }, nil |
| return &Object{ | ||
| Object: model.Object{ | ||
| Name: dirName, | ||
| IsFolder: true, | ||
| }, | ||
| DentryType: "folder", | ||
| }, nil |
| return err | ||
| } | ||
| parts = append(parts, part) | ||
| offset += length |
There was a problem hiding this comment.
这里少了更新进度UpdateProgress,可以参考我上面发的GoogleDrive的例子
Generated with OpenAI Codex
Generated with OpenAI Codex
| return fmt.Errorf("root folder id is empty") | ||
| } | ||
| d.client = newClient() | ||
| if _, err := d.list(ctx, d.RootFolderID); err != nil { |
There was a problem hiding this comment.
@zjhcx 还剩一个槽点就是使用list检测cookie是否有效,你试一下能不能抓到获取用户信息之类的,不需要返回太多数据的api,用来检测cookie的有效性
There was a problem hiding this comment.
@zjhcx 还剩一个槽点就是使用list检测cookie是否有效,你试一下能不能抓到获取用户信息之类的,不需要返回太多数据的api,用来检测cookie的有效性
已改成获取用户的个人信息(https://alidocs.dingtalk.com/portal/api/v1/mine/info)
Generated with OpenAI Codex
Summary / 摘要
Add a new read-only
AliDocdriver for accessing DingDrive through DingTalk Docs, and harden the WPS driver against empty login-state responses so initialization and details queries fail with clear errors instead of unstable behavior.新增
AliDoc驱动,用于通过钉钉文档访问钉盘,支持列出文件、查看文件、删除文件、移动文件、上传文件、创建文件夹、复制文件和重命名文件;同时增强 WPS 驱动在登录状态为空时的错误处理,使初始化和空间信息查询返回明确错误,而不是产生不稳定行为。Add
drivers/alidocwith Cookie-based initialization, folder listing, and file download link resolution.Register the new driver in
drivers/all.goand ignore localalidoc/reverse-engineering materials.Return user-friendly errors in WPS when login state or business company id is missing.
Related frontend changes are needed to add
AliDoci18n entries and alert copy.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:
Testing / 测试
go test ./drivers/alidocgo test ./drivers可正常列出、查看、删除、移动、上传、复制和重命名文本、图片、视频和PDF。可正常创建和移动文件夹
Checklist / 检查清单
/ 我已阅读 CONTRIBUTING。
/ 我确认此贡献符合仓库许可证、贡献规范和行为准则。
gofmt,go fmt, orprettierwhere applicable./ 我已按适用情况使用
gofmt、go fmt或prettier格式化变更代码。/ 我已在适用情况下请求相关维护者或代码所有者审查。
AI Disclosure / AI 使用声明
/ 此 PR 包含 AI 辅助内容。
Tools used / 使用工具:
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-Byattribution./ 我已确保所有 AI 辅助提交都包含
Co-Authored-By归属信息。I can reproduce all AI-assisted content included in this PR without any AI tools.
/ 我可以在没有任何 AI 工具的情况下重现此 PR 中包含的所有 AI 辅助内容。