update: xunlei

This commit is contained in:
Kerwin
2025-09-02 18:30:55 +08:00
parent 2853287b1d
commit 4aab45cda5
3 changed files with 124 additions and 37 deletions

View File

@@ -54,7 +54,6 @@ func (x *XunleiPanService) apiHost(apiType string) string {
return "https://api-pan.xunlei.com"
}
// 工具:自动补全必要 header
func (x *XunleiPanService) setCommonHeader(req *http.Request) {
for k, v := range x.headers {
req.Header.Set(k, v)
@@ -116,6 +115,36 @@ func GetXunleiInstance() *XunleiPanService {
return NewXunleiPanService(nil)
}
func (x *XunleiPanService) getAccessTokenByRefreshToken(refreshToken string) (map[string]interface{}, error) {
// 构造请求体
body := map[string]interface{}{
"client_id": x.clientId,
"grant_type": "refresh_token",
"refresh_token": refreshToken,
}
// 过滤 headers移除 Authorization 和 x-captcha-token
filteredHeaders := make(map[string]string)
for k, v := range x.headers {
if k != "Authorization" && k != "x-captcha-token" {
filteredHeaders[k] = v
}
}
// 调用 API 获取新的 token
resp, err := x.requestXunleiApi("https://xluser-ssl.xunlei.com/v1/auth/token", "POST", body, nil, filteredHeaders)
if err != nil {
return map[string]interface{}{}, fmt.Errorf("获取 access_token 请求失败: %v", err)
}
if resp["code"] != 0 || resp["data"] == nil {
return map[string]interface{}{}, fmt.Errorf("获取 access_token 失败: %v", resp)
}
data := resp["data"].(map[string]interface{})
return data, nil
}
// getAccessToken 获取 Access Token内部包含缓存判断、刷新、保存- 匹配 PHP 版本
func (x *XunleiPanService) getAccessToken() (string, error) {
if x.cksRepo == nil {
@@ -148,43 +177,21 @@ func (x *XunleiPanService) getAccessToken() (string, error) {
return "", fmt.Errorf("未配置迅雷 refresh_token请检查 cks 表的 ck 字段")
}
// 构造请求体
body := map[string]interface{}{
"client_id": x.clientId,
"grant_type": "refresh_token",
"refresh_token": refreshTokenValue,
}
// 过滤 headers移除 Authorization 和 x-captcha-token
filteredHeaders := make(map[string]string)
for k, v := range x.headers {
if k != "Authorization" && k != "x-captcha-token" {
filteredHeaders[k] = v
}
}
// 调用 API 获取新的 token
resp, err := x.requestXunleiApi("https://xluser-ssl.xunlei.com/v1/auth/token", "POST", body, nil, filteredHeaders)
newData, err := x.getAccessTokenByRefreshToken(refreshTokenValue)
if err != nil {
return "", fmt.Errorf("获取 access_token 请求失败: %v", err)
return "", fmt.Errorf("获取 access_token 失败: %v", err)
}
if resp["code"] != 0 || resp["data"] == nil {
return "", fmt.Errorf("获取 access_token 失败: %v", resp)
}
data := resp["data"].(map[string]interface{})
newAccessToken := data["access_token"].(string)
newAccessToken := newData["access_token"].(string)
// 计算过期时间(当前时间 + expires_in - 60 秒缓冲)
expiresAt := currentTime + int64(data["expires_in"].(float64)) - 60
expiresAt := currentTime + int64(newData["expires_in"].(float64)) - 60
// 更新 extra 数据
if extraData.AccessToken == nil {
extraData.AccessToken = &AccessTokenData{}
}
extraData.AccessToken.AccessToken = newAccessToken
extraData.AccessToken.RefreshToken = data["refresh_token"].(string)
extraData.AccessToken.RefreshToken = newData["refresh_token"].(string)
extraData.AccessToken.ExpiresAt = expiresAt
// 保存到数据库

View File

@@ -0,0 +1,79 @@
export const useCookie = () => {
const get = (name: string): string | null => {
if (process.server) {
// 服务端处理
const { req } = useRequestEvent()
const cookies = parse(req.headers.cookie || '')
return cookies[name] || null
} else {
// 客户端处理
const cookieString = document.cookie
const cookies = cookieString.split('; ')
for (const cookie of cookies) {
const [cookieName, cookieValue] = cookie.split('=')
if (cookieName === name) {
return decodeURIComponent(cookieValue)
}
}
return null
}
}
const set = (name: string, value: string, options?: any) => {
if (process.server) {
// 服务端设置 cookie
const { res } = useRequestEvent()
res.setHeader('Set-Cookie', `${name}=${encodeURIComponent(value)}; ${serializeOptions(options)}`)
} else {
// 客户端设置 cookie
document.cookie = `${name}=${encodeURIComponent(value)}; ${serializeOptions(options)}`
}
}
const remove = (name: string) => {
set(name, '', { maxAge: -1 })
}
// 序列化 cookie 选项
const serializeOptions = (options: any = {}): string => {
const {
maxAge,
expires,
path = '/',
domain,
secure,
httpOnly,
sameSite
} = options
let result = ''
if (maxAge !== undefined) result += `Max-Age=${maxAge}; `
if (expires instanceof Date) result += `Expires=${expires.toUTCString()}; `
if (path) result += `Path=${path}; `
if (domain) result += `Domain=${domain}; `
if (secure) result += 'Secure; '
if (httpOnly) result += 'HttpOnly; '
if (sameSite) result += `SameSite=${sameSite}; `
return result
}
// 解析 cookie 字符串
const parse = (cookieString: string): Record<string, string> => {
const cookies: Record<string, string> = {}
cookieString.split(';').forEach(cookie => {
const [name, value] = cookie.split('=')
if (name && value) {
cookies[name.trim()] = decodeURIComponent(value.trim())
}
})
return cookies
}
return {
get,
set,
remove
}
}

View File

@@ -191,7 +191,7 @@
平台类型 <span class="text-red-500">*</span>
</label>
<n-select v-model:value="form.pan_id" placeholder="请选择平台"
:options="platforms.filter(pan => pan.name === 'quark' || pan.name === 'xunlei').map(pan => ({ label: pan.remark, value: pan.id }))"
:options="platforms.filter(pan => panEnables.includes(pan.name)).map(pan => ({ label: pan.remark, value: pan.id }))"
:disabled="showEditModal" required />
<p v-if="showEditModal" class="mt-1 text-xs text-gray-500">编辑时不允许修改平台类型</p>
</div>
@@ -210,14 +210,7 @@
<div v-if="isXunlei">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Authorization <span class="text-red-500">*</span>
</label>
<n-input v-model:value="form.ck" type="textarea" placeholder="请输入Authorization内容 Berear" :rows="4" required />
</div>
<div v-if="isXunlei">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Token <span class="text-red-500">*</span>
refresh_token <span class="text-red-500">*</span>
</label>
<n-input v-model:value="form.ck" type="textarea" placeholder="请输入" :rows="4" required />
</div>
@@ -272,6 +265,14 @@ const form = ref({
remark: ''
})
const cookie = useCookie()
const panEnables = ref(['quark'])
const xunleiEnable = cookie.get('xunleiEnable')
console.log(xunleiEnable)
if (xunleiEnable && xunleiEnable === 'true') {
panEnables.value.push('xunlei')
}
watch(() => form.value.pan_id, (newVal) => {
isQuark.value = false
isXunlei.value = false