Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alist-org
GitHub Repository: alist-org/alist
Path: blob/main/drivers/chaoxing/driver.go
1988 views
1
package chaoxing
2
3
import (
4
"bytes"
5
"context"
6
"encoding/json"
7
"errors"
8
"fmt"
9
"io"
10
"mime/multipart"
11
"net/http"
12
"net/url"
13
"strings"
14
"time"
15
16
"github.com/alist-org/alist/v3/internal/driver"
17
"github.com/alist-org/alist/v3/internal/errs"
18
"github.com/alist-org/alist/v3/internal/model"
19
"github.com/alist-org/alist/v3/internal/op"
20
"github.com/alist-org/alist/v3/pkg/cron"
21
"github.com/alist-org/alist/v3/pkg/utils"
22
"github.com/go-resty/resty/v2"
23
"google.golang.org/appengine/log"
24
)
25
26
type ChaoXing struct {
27
model.Storage
28
Addition
29
cron *cron.Cron
30
config driver.Config
31
conf Conf
32
}
33
34
func (d *ChaoXing) Config() driver.Config {
35
return d.config
36
}
37
38
func (d *ChaoXing) GetAddition() driver.Additional {
39
return &d.Addition
40
}
41
42
func (d *ChaoXing) refreshCookie() error {
43
cookie, err := d.Login()
44
if err != nil {
45
d.Status = err.Error()
46
op.MustSaveDriverStorage(d)
47
return nil
48
}
49
d.Addition.Cookie = cookie
50
op.MustSaveDriverStorage(d)
51
return nil
52
}
53
54
func (d *ChaoXing) Init(ctx context.Context) error {
55
err := d.refreshCookie()
56
if err != nil {
57
log.Errorf(ctx, err.Error())
58
}
59
d.cron = cron.NewCron(time.Hour * 12)
60
d.cron.Do(func() {
61
err = d.refreshCookie()
62
if err != nil {
63
log.Errorf(ctx, err.Error())
64
}
65
})
66
return nil
67
}
68
69
func (d *ChaoXing) Drop(ctx context.Context) error {
70
if d.cron != nil {
71
d.cron.Stop()
72
}
73
return nil
74
}
75
76
func (d *ChaoXing) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
77
files, err := d.GetFiles(dir.GetID())
78
if err != nil {
79
return nil, err
80
}
81
return utils.SliceConvert(files, func(src File) (model.Obj, error) {
82
return fileToObj(src), nil
83
})
84
}
85
86
func (d *ChaoXing) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
87
var resp DownResp
88
ua := d.conf.ua
89
fileId := strings.Split(file.GetID(), "$")[1]
90
_, err := d.requestDownload("/screen/note_note/files/status/"+fileId, http.MethodPost, func(req *resty.Request) {
91
req.SetHeader("User-Agent", ua)
92
}, &resp)
93
if err != nil {
94
return nil, err
95
}
96
u := resp.Download
97
return &model.Link{
98
URL: u,
99
Header: http.Header{
100
"Cookie": []string{d.Cookie},
101
"Referer": []string{d.conf.referer},
102
"User-Agent": []string{ua},
103
},
104
Concurrency: 2,
105
PartSize: 10 * utils.MB,
106
}, nil
107
}
108
109
func (d *ChaoXing) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
110
query := map[string]string{
111
"bbsid": d.Addition.Bbsid,
112
"name": dirName,
113
"pid": parentDir.GetID(),
114
}
115
var resp ListFileResp
116
_, err := d.request("/pc/resource/addResourceFolder", http.MethodGet, func(req *resty.Request) {
117
req.SetQueryParams(query)
118
}, &resp)
119
if err != nil {
120
return err
121
}
122
if resp.Result != 1 {
123
msg := fmt.Sprintf("error:%s", resp.Msg)
124
return errors.New(msg)
125
}
126
return nil
127
}
128
129
func (d *ChaoXing) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
130
query := map[string]string{
131
"bbsid": d.Addition.Bbsid,
132
"folderIds": srcObj.GetID(),
133
"targetId": dstDir.GetID(),
134
}
135
if !srcObj.IsDir() {
136
query = map[string]string{
137
"bbsid": d.Addition.Bbsid,
138
"recIds": strings.Split(srcObj.GetID(), "$")[0],
139
"targetId": dstDir.GetID(),
140
}
141
}
142
var resp ListFileResp
143
_, err := d.request("/pc/resource/moveResource", http.MethodGet, func(req *resty.Request) {
144
req.SetQueryParams(query)
145
}, &resp)
146
if err != nil {
147
return err
148
}
149
if !resp.Status {
150
msg := fmt.Sprintf("error:%s", resp.Msg)
151
return errors.New(msg)
152
}
153
return nil
154
}
155
156
func (d *ChaoXing) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
157
query := map[string]string{
158
"bbsid": d.Addition.Bbsid,
159
"folderId": srcObj.GetID(),
160
"name": newName,
161
}
162
path := "/pc/resource/updateResourceFolderName"
163
if !srcObj.IsDir() {
164
// path = "/pc/resource/updateResourceFileName"
165
// query = map[string]string{
166
// "bbsid": d.Addition.Bbsid,
167
// "recIds": strings.Split(srcObj.GetID(), "$")[0],
168
// "name": newName,
169
// }
170
return errors.New("此网盘不支持修改文件名")
171
}
172
var resp ListFileResp
173
_, err := d.request(path, http.MethodGet, func(req *resty.Request) {
174
req.SetQueryParams(query)
175
}, &resp)
176
if err != nil {
177
return err
178
}
179
if resp.Result != 1 {
180
msg := fmt.Sprintf("error:%s", resp.Msg)
181
return errors.New(msg)
182
}
183
return nil
184
}
185
186
func (d *ChaoXing) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
187
// TODO copy obj, optional
188
return errs.NotImplement
189
}
190
191
func (d *ChaoXing) Remove(ctx context.Context, obj model.Obj) error {
192
query := map[string]string{
193
"bbsid": d.Addition.Bbsid,
194
"folderIds": obj.GetID(),
195
}
196
path := "/pc/resource/deleteResourceFolder"
197
var resp ListFileResp
198
if !obj.IsDir() {
199
path = "/pc/resource/deleteResourceFile"
200
query = map[string]string{
201
"bbsid": d.Addition.Bbsid,
202
"recIds": strings.Split(obj.GetID(), "$")[0],
203
}
204
}
205
_, err := d.request(path, http.MethodGet, func(req *resty.Request) {
206
req.SetQueryParams(query)
207
}, &resp)
208
if err != nil {
209
return err
210
}
211
if resp.Result != 1 {
212
msg := fmt.Sprintf("error:%s", resp.Msg)
213
return errors.New(msg)
214
}
215
return nil
216
}
217
218
func (d *ChaoXing) Put(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) error {
219
var resp UploadDataRsp
220
_, err := d.request("https://noteyd.chaoxing.com/pc/files/getUploadConfig", http.MethodGet, func(req *resty.Request) {
221
}, &resp)
222
if err != nil {
223
return err
224
}
225
if resp.Result != 1 {
226
return errors.New("get upload data error")
227
}
228
body := &bytes.Buffer{}
229
writer := multipart.NewWriter(body)
230
filePart, err := writer.CreateFormFile("file", file.GetName())
231
if err != nil {
232
return err
233
}
234
_, err = utils.CopyWithBuffer(filePart, file)
235
if err != nil {
236
return err
237
}
238
err = writer.WriteField("_token", resp.Msg.Token)
239
if err != nil {
240
return err
241
}
242
err = writer.WriteField("puid", fmt.Sprintf("%d", resp.Msg.Puid))
243
if err != nil {
244
fmt.Println("Error writing param2 to request body:", err)
245
return err
246
}
247
err = writer.Close()
248
if err != nil {
249
return err
250
}
251
r := driver.NewLimitedUploadStream(ctx, &driver.ReaderUpdatingProgress{
252
Reader: &driver.SimpleReaderWithSize{
253
Reader: body,
254
Size: int64(body.Len()),
255
},
256
UpdateProgress: up,
257
})
258
req, err := http.NewRequestWithContext(ctx, "POST", "https://pan-yz.chaoxing.com/upload", r)
259
if err != nil {
260
return err
261
}
262
req.Header.Set("Content-Type", writer.FormDataContentType())
263
req.Header.Set("Content-Length", fmt.Sprintf("%d", body.Len()))
264
resps, err := http.DefaultClient.Do(req)
265
if err != nil {
266
return err
267
}
268
defer resps.Body.Close()
269
bodys, err := io.ReadAll(resps.Body)
270
if err != nil {
271
return err
272
}
273
var fileRsp UploadFileDataRsp
274
err = json.Unmarshal(bodys, &fileRsp)
275
if err != nil {
276
return err
277
}
278
if fileRsp.Msg != "success" {
279
return errors.New(fileRsp.Msg)
280
}
281
uploadDoneParam := UploadDoneParam{Key: fileRsp.ObjectID, Cataid: "100000019", Param: fileRsp.Data}
282
params, err := json.Marshal(uploadDoneParam)
283
if err != nil {
284
return err
285
}
286
query := map[string]string{
287
"bbsid": d.Addition.Bbsid,
288
"pid": dstDir.GetID(),
289
"type": "yunpan",
290
"params": url.QueryEscape("[" + string(params) + "]"),
291
}
292
var respd ListFileResp
293
_, err = d.request("/pc/resource/addResource", http.MethodGet, func(req *resty.Request) {
294
req.SetQueryParams(query)
295
}, &respd)
296
if err != nil {
297
return err
298
}
299
if respd.Result != 1 {
300
msg := fmt.Sprintf("error:%v", resp.Msg)
301
return errors.New(msg)
302
}
303
return nil
304
}
305
306
var _ driver.Driver = (*ChaoXing)(nil)
307
308