mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-07 18:05:30 +08:00
版本号修改
This commit is contained in:
@@ -3,6 +3,7 @@ package protocol
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -21,15 +22,11 @@ const (
|
||||
DeepSeekUploadTargetPath = "/api/v0/file/upload_file"
|
||||
)
|
||||
|
||||
var defaultBaseHeaders = map[string]string{
|
||||
"Host": "chat.deepseek.com",
|
||||
"User-Agent": "DeepSeek/1.8.0 Android/35",
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
"x-client-platform": "android",
|
||||
"x-client-version": "1.8.0",
|
||||
"x-client-locale": "zh_CN",
|
||||
"accept-charset": "UTF-8",
|
||||
var defaultStaticBaseHeaders = map[string]string{
|
||||
"Host": "chat.deepseek.com",
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
"accept-charset": "UTF-8",
|
||||
}
|
||||
|
||||
var defaultSkipContainsPatterns = []string{
|
||||
@@ -47,11 +44,21 @@ var defaultSkipExactPaths = []string{
|
||||
"response/search_status",
|
||||
}
|
||||
|
||||
var BaseHeaders = cloneStringMap(defaultBaseHeaders)
|
||||
var ClientVersion string
|
||||
var BaseHeaders = map[string]string{}
|
||||
var SkipContainsPatterns = cloneStringSlice(defaultSkipContainsPatterns)
|
||||
var SkipExactPathSet = toStringSet(defaultSkipExactPaths)
|
||||
|
||||
type clientConstants struct {
|
||||
Name string `json:"name"`
|
||||
Platform string `json:"platform"`
|
||||
Version string `json:"version"`
|
||||
AndroidAPILevel string `json:"android_api_level"`
|
||||
Locale string `json:"locale"`
|
||||
}
|
||||
|
||||
type sharedConstants struct {
|
||||
Client clientConstants `json:"client"`
|
||||
BaseHeaders map[string]string `json:"base_headers"`
|
||||
SkipContainsPattern []string `json:"skip_contains_patterns"`
|
||||
SkipExactPaths []string `json:"skip_exact_paths"`
|
||||
@@ -63,19 +70,68 @@ var sharedConstantsJSON []byte
|
||||
func init() {
|
||||
cfg := sharedConstants{}
|
||||
if err := json.Unmarshal(sharedConstantsJSON, &cfg); err != nil {
|
||||
return
|
||||
}
|
||||
if len(cfg.BaseHeaders) > 0 {
|
||||
BaseHeaders = cloneStringMap(cfg.BaseHeaders)
|
||||
panic(fmt.Errorf("load DeepSeek shared constants: %w", err))
|
||||
}
|
||||
applySharedConstants(cfg)
|
||||
}
|
||||
|
||||
func applySharedConstants(cfg sharedConstants) {
|
||||
client := normalizeClientConstants(cfg.Client)
|
||||
ClientVersion = client.Version
|
||||
BaseHeaders = buildBaseHeaders(client, cfg.BaseHeaders)
|
||||
SkipContainsPatterns = cloneStringSlice(defaultSkipContainsPatterns)
|
||||
if len(cfg.SkipContainsPattern) > 0 {
|
||||
SkipContainsPatterns = cloneStringSlice(cfg.SkipContainsPattern)
|
||||
}
|
||||
SkipExactPathSet = toStringSet(defaultSkipExactPaths)
|
||||
if len(cfg.SkipExactPaths) > 0 {
|
||||
SkipExactPathSet = toStringSet(cfg.SkipExactPaths)
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeClientConstants(in clientConstants) clientConstants {
|
||||
if in.Name == "" {
|
||||
in.Name = "DeepSeek"
|
||||
}
|
||||
if in.Platform == "" {
|
||||
in.Platform = "android"
|
||||
}
|
||||
if in.AndroidAPILevel == "" {
|
||||
in.AndroidAPILevel = "35"
|
||||
}
|
||||
if in.Locale == "" {
|
||||
in.Locale = "zh_CN"
|
||||
}
|
||||
return in
|
||||
}
|
||||
|
||||
func buildBaseHeaders(client clientConstants, overrides map[string]string) map[string]string {
|
||||
out := cloneStringMap(defaultStaticBaseHeaders)
|
||||
for k, v := range overrides {
|
||||
if k == "" || v == "" {
|
||||
continue
|
||||
}
|
||||
out[k] = v
|
||||
}
|
||||
if client.Name != "" && client.Version != "" {
|
||||
userAgent := client.Name + "/" + client.Version
|
||||
if client.Platform == "android" && client.AndroidAPILevel != "" {
|
||||
userAgent += " Android/" + client.AndroidAPILevel
|
||||
}
|
||||
out["User-Agent"] = userAgent
|
||||
}
|
||||
if client.Platform != "" {
|
||||
out["x-client-platform"] = client.Platform
|
||||
}
|
||||
if client.Version != "" {
|
||||
out["x-client-version"] = client.Version
|
||||
}
|
||||
if client.Locale != "" {
|
||||
out["x-client-locale"] = client.Locale
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func cloneStringMap(in map[string]string) map[string]string {
|
||||
out := make(map[string]string, len(in))
|
||||
for k, v := range in {
|
||||
@@ -103,6 +159,6 @@ func toStringSet(in []string) map[string]struct{} {
|
||||
|
||||
const (
|
||||
KeepAliveTimeout = 5
|
||||
StreamIdleTimeout = 30
|
||||
StreamIdleTimeout = 90
|
||||
MaxKeepaliveCount = 10
|
||||
)
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
{
|
||||
"client": {
|
||||
"name": "DeepSeek",
|
||||
"platform": "android",
|
||||
"version": "2.0.1",
|
||||
"android_api_level": "35",
|
||||
"locale": "zh_CN"
|
||||
},
|
||||
"base_headers": {
|
||||
"Host": "chat.deepseek.com",
|
||||
"User-Agent": "DeepSeek/1.8.0 Android/35",
|
||||
"Accept": "application/json",
|
||||
"x-client-platform": "android",
|
||||
"x-client-version": "1.8.0",
|
||||
"x-client-locale": "zh_CN",
|
||||
"Content-Type": "application/json",
|
||||
"accept-charset": "UTF-8"
|
||||
},
|
||||
"skip_contains_patterns": [
|
||||
|
||||
@@ -1,11 +1,32 @@
|
||||
package protocol
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSharedConstantsLoaded(t *testing.T) {
|
||||
cfg := sharedConstants{}
|
||||
if err := json.Unmarshal(sharedConstantsJSON, &cfg); err != nil {
|
||||
t.Fatalf("failed to parse shared constants: %v", err)
|
||||
}
|
||||
client := normalizeClientConstants(cfg.Client)
|
||||
if ClientVersion != client.Version {
|
||||
t.Fatalf("unexpected client version=%q", ClientVersion)
|
||||
}
|
||||
wantUserAgent := client.Name + "/" + client.Version + " Android/" + client.AndroidAPILevel
|
||||
if BaseHeaders["User-Agent"] != wantUserAgent {
|
||||
t.Fatalf("unexpected user agent=%q", BaseHeaders["User-Agent"])
|
||||
}
|
||||
if BaseHeaders["x-client-platform"] != "android" {
|
||||
t.Fatalf("unexpected base header x-client-platform=%q", BaseHeaders["x-client-platform"])
|
||||
}
|
||||
if BaseHeaders["x-client-version"] != ClientVersion {
|
||||
t.Fatalf("unexpected base header x-client-version=%q", BaseHeaders["x-client-version"])
|
||||
}
|
||||
if BaseHeaders["Content-Type"] != "application/json" {
|
||||
t.Fatalf("unexpected base header Content-Type=%q", BaseHeaders["Content-Type"])
|
||||
}
|
||||
if len(SkipContainsPatterns) == 0 {
|
||||
t.Fatal("expected skip contains patterns to be loaded")
|
||||
}
|
||||
@@ -13,3 +34,23 @@ func TestSharedConstantsLoaded(t *testing.T) {
|
||||
t.Fatal("expected response/search_status in exact skip path set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientHeadersDerivedFromSharedVersion(t *testing.T) {
|
||||
client := normalizeClientConstants(clientConstants{
|
||||
Name: "DeepSeek",
|
||||
Platform: "android",
|
||||
Version: "9.8.7",
|
||||
AndroidAPILevel: "35",
|
||||
Locale: "zh_CN",
|
||||
})
|
||||
headers := buildBaseHeaders(client, map[string]string{
|
||||
"User-Agent": "stale",
|
||||
"x-client-version": "stale",
|
||||
})
|
||||
if headers["User-Agent"] != "DeepSeek/9.8.7 Android/35" {
|
||||
t.Fatalf("unexpected derived user agent=%q", headers["User-Agent"])
|
||||
}
|
||||
if headers["x-client-version"] != "9.8.7" {
|
||||
t.Fatalf("unexpected derived client version=%q", headers["x-client-version"])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,17 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const DEFAULT_CLIENT = Object.freeze({
|
||||
name: 'DeepSeek',
|
||||
platform: 'android',
|
||||
androidApiLevel: '35',
|
||||
locale: 'zh_CN',
|
||||
});
|
||||
|
||||
const DEFAULT_BASE_HEADERS = Object.freeze({
|
||||
Host: 'chat.deepseek.com',
|
||||
'User-Agent': 'DeepSeek/1.8.0 Android/35',
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'x-client-platform': 'android',
|
||||
'x-client-version': '1.8.0',
|
||||
'x-client-locale': 'zh_CN',
|
||||
'accept-charset': 'UTF-8',
|
||||
});
|
||||
|
||||
@@ -29,38 +32,96 @@ const DEFAULT_SKIP_EXACT_PATHS = Object.freeze([
|
||||
'response/search_status',
|
||||
]);
|
||||
|
||||
function loadSharedConstants() {
|
||||
const sharedPath = path.resolve(__dirname, '../../internal/deepseek/constants_shared.json');
|
||||
try {
|
||||
const raw = fs.readFileSync(sharedPath, 'utf8');
|
||||
const parsed = JSON.parse(raw);
|
||||
const baseHeaders = parsed && typeof parsed.base_headers === 'object' && !Array.isArray(parsed.base_headers)
|
||||
? { ...DEFAULT_BASE_HEADERS, ...parsed.base_headers }
|
||||
: { ...DEFAULT_BASE_HEADERS };
|
||||
const skipPatterns = Array.isArray(parsed && parsed.skip_contains_patterns)
|
||||
? parsed.skip_contains_patterns.filter((v) => typeof v === 'string' && v !== '')
|
||||
: [...DEFAULT_SKIP_PATTERNS];
|
||||
const skipExactPaths = Array.isArray(parsed && parsed.skip_exact_paths)
|
||||
? parsed.skip_exact_paths.filter((v) => typeof v === 'string' && v !== '')
|
||||
: [...DEFAULT_SKIP_EXACT_PATHS];
|
||||
return {
|
||||
baseHeaders,
|
||||
skipPatterns,
|
||||
skipExactPaths,
|
||||
};
|
||||
} catch (_err) {
|
||||
return {
|
||||
baseHeaders: { ...DEFAULT_BASE_HEADERS },
|
||||
skipPatterns: [...DEFAULT_SKIP_PATTERNS],
|
||||
skipExactPaths: [...DEFAULT_SKIP_EXACT_PATHS],
|
||||
};
|
||||
function asNonEmptyString(value) {
|
||||
return typeof value === 'string' && value !== '' ? value : '';
|
||||
}
|
||||
|
||||
function normalizeClient(raw) {
|
||||
const client = raw && typeof raw === 'object' && !Array.isArray(raw) ? raw : {};
|
||||
return {
|
||||
name: asNonEmptyString(client.name) || DEFAULT_CLIENT.name,
|
||||
platform: asNonEmptyString(client.platform) || DEFAULT_CLIENT.platform,
|
||||
version: asNonEmptyString(client.version),
|
||||
androidApiLevel: asNonEmptyString(client.android_api_level) || DEFAULT_CLIENT.androidApiLevel,
|
||||
locale: asNonEmptyString(client.locale) || DEFAULT_CLIENT.locale,
|
||||
};
|
||||
}
|
||||
|
||||
function buildBaseHeaders(parsed, client) {
|
||||
const rawBaseHeaders = parsed && typeof parsed.base_headers === 'object' && !Array.isArray(parsed.base_headers)
|
||||
? parsed.base_headers
|
||||
: {};
|
||||
const baseHeaders = { ...DEFAULT_BASE_HEADERS, ...rawBaseHeaders };
|
||||
if (client.name && client.version) {
|
||||
const androidSuffix = client.platform === 'android' && client.androidApiLevel
|
||||
? ` Android/${client.androidApiLevel}`
|
||||
: '';
|
||||
baseHeaders['User-Agent'] = `${client.name}/${client.version}${androidSuffix}`;
|
||||
}
|
||||
if (client.platform) {
|
||||
baseHeaders['x-client-platform'] = client.platform;
|
||||
}
|
||||
if (client.version) {
|
||||
baseHeaders['x-client-version'] = client.version;
|
||||
}
|
||||
if (client.locale) {
|
||||
baseHeaders['x-client-locale'] = client.locale;
|
||||
}
|
||||
return baseHeaders;
|
||||
}
|
||||
|
||||
function sharedConstantsPaths() {
|
||||
return [
|
||||
path.resolve(__dirname, '../../deepseek/protocol/constants_shared.json'),
|
||||
path.resolve(process.cwd(), 'internal/deepseek/protocol/constants_shared.json'),
|
||||
];
|
||||
}
|
||||
|
||||
function readSharedConstants() {
|
||||
try {
|
||||
return require('../../deepseek/protocol/constants_shared.json');
|
||||
} catch (_err) {
|
||||
// Fall through to filesystem candidates for test and local execution variants.
|
||||
}
|
||||
for (const sharedPath of sharedConstantsPaths()) {
|
||||
try {
|
||||
const raw = fs.readFileSync(sharedPath, 'utf8');
|
||||
return JSON.parse(raw);
|
||||
} catch (_err) {
|
||||
// Try the next candidate path; fall back to in-file structural defaults below.
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
function loadSharedConstants() {
|
||||
const parsed = readSharedConstants();
|
||||
const client = normalizeClient(parsed && parsed.client);
|
||||
const skipPatterns = Array.isArray(parsed && parsed.skip_contains_patterns)
|
||||
? parsed.skip_contains_patterns.filter((v) => typeof v === 'string' && v !== '')
|
||||
: [...DEFAULT_SKIP_PATTERNS];
|
||||
const skipExactPaths = Array.isArray(parsed && parsed.skip_exact_paths)
|
||||
? parsed.skip_exact_paths.filter((v) => typeof v === 'string' && v !== '')
|
||||
: [...DEFAULT_SKIP_EXACT_PATHS];
|
||||
return {
|
||||
client,
|
||||
baseHeaders: buildBaseHeaders(parsed, client),
|
||||
skipPatterns,
|
||||
skipExactPaths,
|
||||
};
|
||||
}
|
||||
|
||||
const shared = loadSharedConstants();
|
||||
|
||||
module.exports = {
|
||||
CLIENT: Object.freeze({ ...shared.client }),
|
||||
CLIENT_VERSION: shared.client.version,
|
||||
BASE_HEADERS: Object.freeze(shared.baseHeaders),
|
||||
SKIP_PATTERNS: Object.freeze(shared.skipPatterns),
|
||||
SKIP_EXACT_PATHS: new Set(shared.skipExactPaths),
|
||||
__test: {
|
||||
buildBaseHeaders,
|
||||
normalizeClient,
|
||||
sharedConstantsPaths,
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user