initial commit

This commit is contained in:
2026-07-31 14:21:48 +03:00
commit 92ceb8bec3
22 changed files with 3104 additions and 0 deletions
+124
View File
@@ -0,0 +1,124 @@
package deepseek
import (
"crypto/rand"
"encoding/base64"
"errors"
"fmt"
"net/http"
"net/url"
"strings"
)
// DeviceIDFromJar returns the base64-encoded value of the first DeepSeek
// thumbcache cookie in jar.
func (api *Client) DeviceIDFromJar(jar http.CookieJar) (string, error) {
if jar == nil {
return "", errors.New("cookie jar is nil")
}
u, err := url.Parse("https://chat.deepseek.com")
if err != nil {
return "", fmt.Errorf("parse DeepSeek URL: %w", err)
}
for _, cookie := range jar.Cookies(u) {
if strings.HasPrefix(cookie.Name, ".thumbcache_") {
if cookie.Value == "" {
return "", errors.New("thumbcache cookie is empty")
}
deviceID := base64.StdEncoding.EncodeToString(
[]byte(cookie.Value),
)
return deviceID, nil
}
}
return "", errors.New("thumbcache cookie not found")
}
// LoginReq is the request body used to authenticate a user.
type LoginReq struct {
DeviceID string `json:"device_id"`
OS string `json:"os"`
Email string `json:"email"`
Password string `json:"password"`
}
// LoginRes contains the user returned by a successful login.
type LoginRes struct {
User User `json:"user"`
}
// User describes an authenticated DeepSeek user.
type User struct {
ID string `json:"id"`
Token string `json:"token"`
Email string `json:"email"`
}
// Login authenticates with email and password and stores the returned bearer
// token on api. It uses a random device ID when no provider is configured.
func (api *Client) Login(email, password string) error {
var deviceID string
var err error
if api.deviceIDProvider != nil {
deviceID, err = api.deviceIDProvider.Get()
} else {
deviceID, err = RandomDeviceIDProvider().Get()
}
if err != nil {
return err
}
body := LoginReq{
DeviceID: deviceID,
OS: "ios",
Email: email,
Password: password,
}
req := NewRequest[LoginRes]("POST", "users/login", body)
resp, err := req.Do(api)
if err != nil {
return err
}
defer resp.Body.Close()
response, err := req.unmarshallBizResponse(resp)
if err != nil {
return err
}
api.SetToken(response.Data.Data.User.Token)
return nil
}
// DeviceIDProvider supplies the device ID sent during login.
type DeviceIDProvider interface {
Get() (string, error)
}
type randomDeviceIDProvider struct{}
// RandomDeviceIDProvider returns a provider that generates a random device ID
// for every call to Get.
func RandomDeviceIDProvider() randomDeviceIDProvider {
return randomDeviceIDProvider{}
}
func (p randomDeviceIDProvider) Get() (string, error) {
raw := make([]byte, 64)
if _, err := rand.Read(raw); err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(raw), nil
}
type staticDeviceIDProvider struct {
id string
}
// StaticDeviceIDProvider returns a provider that always returns id.
func StaticDeviceIDProvider(id string) staticDeviceIDProvider {
return staticDeviceIDProvider{id: id}
}
func (p staticDeviceIDProvider) Get() (string, error) { return p.id, nil }