Files

103 lines
3.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package service
import (
"context"
"errors"
"fmt"
"log"
"net/url"
"strings"
"affiliate_dash/internal/model"
)
// TokenPackageLinkResult 是 Token 所属上游打包页面的定位链接。
type TokenPackageLinkResult struct {
PackageID int64 `json:"package_id"`
ShareCode string `json:"share_code"`
URL string `json:"url"`
}
// TokenPackageLink 返回 Token 所属上游包页面的跳转链接。
// 只对本地已保存分享码的新包生效;历史包不向上游反查。
func (s *RockService) TokenPackageLink(ctx context.Context, tokenID uint) (*TokenPackageLinkResult, error) {
var token model.RockToken
if err := s.db.WithContext(ctx).First(&token, tokenID).Error; err != nil {
return nil, err
}
if token.PackageID == nil || *token.PackageID <= 0 {
return nil, errors.New("该 Token 没有关联上游打包记录,无法跳转上游")
}
cfg, err := s.GetConfig(ctx)
if err != nil {
return nil, err
}
shareCode := strings.TrimSpace(token.PackageShareCode)
if shareCode == "" {
shareCode, err = s.resolvePackageShareCode(ctx, *token.PackageID, cfg.BearerToken)
if err != nil {
return nil, err
}
// 反查成功后回填同包 Token,后续点击无需再请求上游。
if updateErr := s.db.WithContext(ctx).Model(&model.RockToken{}).
Where("package_id = ? AND package_share_code = ''", *token.PackageID).
Update("package_share_code", shareCode).Error; updateErr != nil {
log.Printf("[RockService] 回填 package_share_code 失败 package_id=%d: %v", *token.PackageID, updateErr)
}
}
base := strings.TrimRight(strings.TrimSpace(cfg.BaseURL), "/")
if base == "" {
base = model.RockDefaultBaseURL
}
return &TokenPackageLinkResult{
PackageID: *token.PackageID,
ShareCode: shareCode,
URL: fmt.Sprintf("%s/#/package/%s", base, url.PathEscape(shareCode)),
}, nil
}
// resolvePackageShareCode 在本地没有分享码时,按 package_id 从上游包列表反查。
// 历史 Token 只落了 package_id,package_share_code 是后续版本才开始保存的。
func (s *RockService) resolvePackageShareCode(ctx context.Context, packageID int64, bearerToken string) (string, error) {
if packageID <= 0 {
return "", errors.New("该 Token 没有关联上游打包记录,无法跳转上游")
}
bearer := strings.TrimSpace(bearerToken)
if bearer == "" {
return "", errors.New("该 Token 缺少上游包分享码,且未配置 0666.pro Bearer Token,无法反查上游包")
}
// 最多翻 20 页,防止上游分页异常导致死循环。
for page := 1; page <= 20; page++ {
resp, err := s.client.ListPackages(ctx, bearer, page, 100)
if err != nil {
return "", fmt.Errorf("反查上游包分享码失败: %w", err)
}
if resp == nil {
break
}
for _, pkg := range resp.Packages {
if pkg.ID != packageID {
continue
}
code := strings.TrimSpace(pkg.ShareCode)
if code == "" {
return "", errors.New("上游该包未返回分享码,无法跳转上游")
}
return code, nil
}
if resp.Pagination.TotalPages > 0 {
if page >= resp.Pagination.TotalPages {
break
}
continue
}
if len(resp.Packages) == 0 {
break
}
}
return "", errors.New("上游未找到该 Token 所属打包记录(可能已被清理),无法跳转上游")
}