Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d06f8b1
feat(drivers/alidoc): add DingTalk Docs driver
zjhcx May 30, 2026
3dfa30c
chore(drivers/alidoc): update metadata copy
zjhcx May 30, 2026
957d341
chore(drivers/alidoc): update read-only alert copy
zjhcx May 30, 2026
fc36dca
chore(gitignore): remove alidoc ignore rule
zjhcx May 30, 2026
640912f
feat(alidoc): support upload move and recycle delete
zjhcx May 31, 2026
c1205eb
fix(alidoc): commit uploaded files after oss transfer
zjhcx May 31, 2026
4330be2
feat(alidoc): support mkdir copy and rename
zjhcx May 31, 2026
08b031e
chore(alidoc): remove unused readonly helper
zjhcx May 31, 2026
b73616e
chore(alidoc): remove driver alert copy
zjhcx May 31, 2026
a4b78d0
Merge branch 'OpenListTeam:main' into main
zjhcx Jun 1, 2026
5242f65
refactor(alidoc): simplify id-based driver behavior
zjhcx Jun 1, 2026
25475b6
refactor(alidoc): stream multipart uploads directly
zjhcx Jun 1, 2026
c59fca8
refactor(alidoc): use retry helper for multipart uploads
zjhcx Jun 1, 2026
64bd329
Update drivers/alidoc/driver.go
zjhcx Jun 1, 2026
151c63a
refactor(alidoc): simplify write operation responses
zjhcx Jun 1, 2026
939abb9
fix(alidoc): update multipart upload progress
zjhcx Jun 1, 2026
9d441b9
docs(readme): sync DingTalk Docs support across translations
zjhcx Jun 2, 2026
b8e1388
refactor(alidoc): simplify file operations and remove redundant checks
j2rong4cn Jun 2, 2026
79f5d74
fix(wps): update login state handling and improve error messages
j2rong4cn Jun 2, 2026
6190dab
fix(alidoc): validate cookie with mine info endpoint
zjhcx Jun 2, 2026
6ea7d88
fix(alidoc): skip root folder listing during init
zjhcx Jun 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ Thank you for your support and understanding of the OpenList project.
- [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
Expand Down
1 change: 1 addition & 0 deletions README_cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ OpenList 是一个由 OpenList 团队独立维护的开源项目,遵循 AGPL-3
- [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] 画廊模式下的图片预览
Expand Down
1 change: 1 addition & 0 deletions README_ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ OpenListプロジェクトへのご支援とご理解をありがとうござい
- [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、コード、テキストなど)
Expand Down
1 change: 1 addition & 0 deletions README_nl.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ Dank u voor uw ondersteuning en begrip
- [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
Expand Down
147 changes: 147 additions & 0 deletions drivers/alidoc/driver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package alidoc

import (
"context"
"fmt"
"net/http"
"strings"

"github.com/OpenListTeam/OpenList/v4/drivers/base"
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/model"
"github.com/go-resty/resty/v2"
)

type AliDoc struct {
model.Storage
Addition

client *resty.Client
}

func (d *AliDoc) Config() driver.Config {
return config
}

func (d *AliDoc) GetAddition() driver.Additional {
return &d.Addition
}

func (d *AliDoc) Init(ctx context.Context) error {
d.Cookie = strings.TrimSpace(d.Cookie)
d.RootFolderID = strings.TrimSpace(d.RootFolderID)
if d.Cookie == "" {
return fmt.Errorf("cookie is empty")
}
if d.RootFolderID == "" {
return fmt.Errorf("root folder id is empty")
}
d.client = newClient()
if err := d.checkCookie(ctx); err != nil {
return err
}
return nil
}

func (d *AliDoc) Drop(ctx context.Context) error {
d.client = nil
return nil
}

func (d *AliDoc) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
items, err := d.list(ctx, dir.GetID())
if err != nil {
return nil, err
}

objs := make([]model.Obj, 0, len(items))
for _, item := range items {
if strings.TrimSpace(item.DentryUUID) == "" || strings.TrimSpace(item.Name) == "" {
continue
}
objs = append(objs, toObj(item))
}
return objs, nil
}

func (d *AliDoc) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
if file.IsDir() {
return nil, fmt.Errorf("alidoc does not support directory links")
}
resp, err := d.download(ctx, file.GetID())
if err != nil {
return nil, err
}
url, err := firstDownloadURL(resp)
if err != nil {
return nil, err
}
return &model.Link{
URL: url,
Header: http.Header{
"User-Agent": []string{base.UserAgent},
"Referer": []string{apiBase + "/"},
},
}, nil
}

func (d *AliDoc) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) (model.Obj, error) {
err := d.post(ctx, "/box/api/v2/dentry/createfolder", map[string]string{
"dentryType": "folder",
"name": dirName,
"parentDentryUuid": parentDir.GetID(),
"conflictHandleStrategy": "auto_rename",
})
if err != nil {
return nil, err
}
return nil, nil
}

func (d *AliDoc) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
err := d.post(ctx, "/box/api/v2/dentry/move", map[string]interface{}{
"targetParentDentryUuid": dstDir.GetID(),
"sourceDentryUuid": srcObj.GetID(),
"operateFrom": 1,
})
if err != nil {
return nil, err
}
return srcObj, nil
}

func (d *AliDoc) Rename(ctx context.Context, srcObj model.Obj, newName string) (model.Obj, error) {
err := d.post(ctx, "/box/api/v2/dentry/rename", map[string]string{
"dentryUuid": srcObj.GetID(),
"name": newName,
})
if err != nil {
return nil, err
}
srcObj.(*model.Object).Name = newName
return srcObj, nil
}

func (d *AliDoc) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
return d.post(ctx, "/box/api/v2/dentry/copy", map[string]interface{}{
"sourceDentryUuid": srcObj.GetID(),
"targetParentDentryUuid": dstDir.GetID(),
"operateFrom": 1,
"onlyCopyMeta": false,
})
}

func (d *AliDoc) Remove(ctx context.Context, obj model.Obj) error {
return d.post(ctx, "/box/api/v1/dentry/recycle", map[string]string{
"dentryUuid": obj.GetID(),
})
}

var (
_ driver.Driver = (*AliDoc)(nil)
_ driver.MkdirResult = (*AliDoc)(nil)
_ driver.MoveResult = (*AliDoc)(nil)
_ driver.RenameResult = (*AliDoc)(nil)
_ driver.Copy = (*AliDoc)(nil)
_ driver.Remove = (*AliDoc)(nil)
)
23 changes: 23 additions & 0 deletions drivers/alidoc/meta.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package alidoc

import (
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/op"
)

type Addition struct {
driver.RootID
Cookie string `json:"cookie" type:"text" required:"true" help:"钉钉文档网页 Cookie"`
}

var config = driver.Config{
Name: "AliDoc",
LocalSort: true,
DefaultRoot: "",
}

func init() {
op.RegisterDriver(func() driver.Driver {
return &AliDoc{}
})
}
87 changes: 87 additions & 0 deletions drivers/alidoc/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package alidoc

type apiResp struct {
Status int `json:"status"`
IsSuccess bool `json:"isSuccess"`
Message string `json:"message"`
Msg string `json:"msg"`
}

func (r apiResp) ErrMessage() string {
if r.Message != "" {
return r.Message
}
if r.Msg != "" {
return r.Msg
}
return ""
}

type listResp struct {
apiResp
Data listData `json:"data"`
}

type listData struct {
Children []dentry `json:"children"`
}

type dentry struct {
DentryType string `json:"dentryType"`
DentryUUID string `json:"dentryUuid"`
ParentDentryUUID string `json:"parentDentryUuid"`
Name string `json:"name"`
Path string `json:"path"`
FileSize int64 `json:"fileSize"`
CreatedTime int64 `json:"createdTime"`
UpdatedTime int64 `json:"updatedTime"`
ContentType string `json:"contentType"`
Extension string `json:"extension"`
DentryStatistic struct {
ChildrenCount int `json:"childrenCount"`
} `json:"dentryStatistic"`
URL struct {
PCChildAppPreviewURL string `json:"pcChildAppPreviewUrl"`
PCChildAppURL string `json:"pcChildAppUrl"`
} `json:"url"`
}

type downloadResp struct {
apiResp
Data downloadData `json:"data"`
}

type downloadData struct {
OSSURLPreSignatureInfo struct {
PreSignURLs []string `json:"preSignUrls"`
} `json:"ossUrlPreSignatureInfo"`
}

type uploadInfoResp struct {
apiResp
Data uploadInfoData `json:"data"`
}

type uploadInfoData struct {
CurrentTimestamp int64 `json:"currentTimestamp"`
FileUploadProtocolConfig uploadProtocolConfig `json:"fileUploadProtocolConfig"`
STSSignatureInfo uploadSTSSignatureInfo `json:"stsSignatureInfo"`
UploadKey string `json:"uploadKey"`
UploadType string `json:"uploadType"`
}

type uploadProtocolConfig struct {
MinPartSize int64 `json:"minPartSize"`
}

type uploadSTSSignatureInfo struct {
AccelerateCname string `json:"accelerateCname"`
AccessKeyID string `json:"accessKeyId"`
AccessKeySecret string `json:"accessKeySecret"`
AccessToken string `json:"accessToken"`
AccessTokenExpiration int64 `json:"accessTokenExpiration"`
Bucket string `json:"bucket"`
Cname string `json:"cname"`
EndPoint string `json:"endPoint"`
ObjectKey string `json:"objectKey"`
}
Loading