mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-10 23:36:37 +08:00
Revert "feat(cloud): 115/夸克网盘 providers with cookie + QR login and 302 playback"
This reverts commit c6455103e6.
This commit is contained in:
@@ -1,160 +0,0 @@
|
||||
package cloud
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// quarkProvider implements the 夸克网盘 cloud disk using cookie auth.
|
||||
//
|
||||
// Quark's web API is plain JSON over HTTPS keyed by a session cookie; no
|
||||
// request-body encryption is required (unlike 115). The resolved download_url
|
||||
// is tied to the session, so playback runs in proxy mode by default.
|
||||
type quarkProvider struct {
|
||||
cookie string
|
||||
ua string
|
||||
base string // override for tests; defaults to quarkBase
|
||||
client *http.Client
|
||||
proxy bool
|
||||
}
|
||||
|
||||
const quarkBase = "https://drive-pc.quark.cn/1/clouddrive"
|
||||
|
||||
func newQuark(cfg map[string]any, client *http.Client) *quarkProvider {
|
||||
base := str(cfg["base"])
|
||||
if base == "" {
|
||||
base = quarkBase
|
||||
}
|
||||
ua := str(cfg["ua"])
|
||||
if ua == "" {
|
||||
ua = defaultUA
|
||||
}
|
||||
// Quark download links require the session cookie + UA, so the host must
|
||||
// reverse-proxy unless the admin explicitly opts into raw 302.
|
||||
proxy := true
|
||||
if _, ok := cfg["force_302"]; ok && boolish(cfg["force_302"]) {
|
||||
proxy = false
|
||||
}
|
||||
return &quarkProvider{
|
||||
cookie: str(cfg["cookie"]),
|
||||
ua: ua,
|
||||
base: strings.TrimRight(base, "/"),
|
||||
client: client,
|
||||
proxy: proxy,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *quarkProvider) Type() string { return TypeQuark }
|
||||
|
||||
func (q *quarkProvider) do(ctx context.Context, method, path string, body io.Reader) (*http.Response, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, method, q.base+path, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Cookie", q.cookie)
|
||||
req.Header.Set("User-Agent", q.ua)
|
||||
req.Header.Set("Accept", "application/json, text/plain, */*")
|
||||
req.Header.Set("Referer", "https://pan.quark.cn/")
|
||||
if body != nil {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
return q.client.Do(req)
|
||||
}
|
||||
|
||||
type quarkResp struct {
|
||||
Status int `json:"status"`
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data json.RawMessage `json:"data"`
|
||||
}
|
||||
|
||||
func (q *quarkProvider) Ping(ctx context.Context) error {
|
||||
if q.cookie == "" {
|
||||
return fmt.Errorf("quark: missing cookie")
|
||||
}
|
||||
_, err := q.List(ctx, "0")
|
||||
return err
|
||||
}
|
||||
|
||||
func (q *quarkProvider) List(ctx context.Context, dirID string) ([]FileEntry, error) {
|
||||
if dirID == "" {
|
||||
dirID = "0"
|
||||
}
|
||||
path := fmt.Sprintf("/file/sort?pr=ucpro&fr=pc&uc_param_str=&pdir_fid=%s&_page=1&_size=100&_fetch_total=1&_sort=file_type:asc,updated_at:desc", dirID)
|
||||
resp, err := q.do(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var r quarkResp
|
||||
if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
|
||||
return nil, fmt.Errorf("quark: decode list: %w", err)
|
||||
}
|
||||
if r.Code != 0 && r.Status != 200 {
|
||||
return nil, fmt.Errorf("quark: list failed: %s", r.Message)
|
||||
}
|
||||
var data struct {
|
||||
List []struct {
|
||||
Fid string `json:"fid"`
|
||||
FileName string `json:"file_name"`
|
||||
Dir bool `json:"dir"`
|
||||
Size int64 `json:"size"`
|
||||
} `json:"list"`
|
||||
}
|
||||
if err := json.Unmarshal(r.Data, &data); err != nil {
|
||||
return nil, fmt.Errorf("quark: decode list data: %w", err)
|
||||
}
|
||||
out := make([]FileEntry, 0, len(data.List))
|
||||
for _, it := range data.List {
|
||||
out = append(out, FileEntry{
|
||||
ID: it.Fid,
|
||||
Name: it.FileName,
|
||||
IsDir: it.Dir,
|
||||
Size: it.Size,
|
||||
})
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (q *quarkProvider) Resolve(ctx context.Context, fileRef string) (*DirectLink, error) {
|
||||
if fileRef == "" {
|
||||
return nil, fmt.Errorf("quark: empty file id")
|
||||
}
|
||||
payload, _ := json.Marshal(map[string]any{"fids": []string{fileRef}})
|
||||
resp, err := q.do(ctx, http.MethodPost, "/file/download?pr=ucpro&fr=pc&uc_param_str=", bytes.NewReader(payload))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var r quarkResp
|
||||
if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
|
||||
return nil, fmt.Errorf("quark: decode download: %w", err)
|
||||
}
|
||||
if r.Code != 0 && r.Status != 200 {
|
||||
return nil, fmt.Errorf("quark: download failed: %s", r.Message)
|
||||
}
|
||||
var data []struct {
|
||||
DownloadURL string `json:"download_url"`
|
||||
Fid string `json:"fid"`
|
||||
}
|
||||
if err := json.Unmarshal(r.Data, &data); err != nil {
|
||||
return nil, fmt.Errorf("quark: decode download data: %w", err)
|
||||
}
|
||||
if len(data) == 0 || data[0].DownloadURL == "" {
|
||||
return nil, fmt.Errorf("quark: no download url returned")
|
||||
}
|
||||
return &DirectLink{
|
||||
URL: data[0].DownloadURL,
|
||||
Headers: map[string]string{
|
||||
"Cookie": q.cookie,
|
||||
"User-Agent": q.ua,
|
||||
"Referer": "https://pan.quark.cn/",
|
||||
},
|
||||
Proxy: q.proxy,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user