Merge branch 'master' of https://git.yunzer.cn/yunzerwebsite/yunzerwebsiteallinone
This commit is contained in:
commit
080db544ea
117
go/controllers/api_cursor_detect.go
Normal file
117
go/controllers/api_cursor_detect.go
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"server/models"
|
||||||
|
|
||||||
|
"github.com/beego/beego/v2/client/orm"
|
||||||
|
beego "github.com/beego/beego/v2/server/web"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ApiCursorDetectController Cursor Token 顺序读取接口(不改变号池状态)
|
||||||
|
//
|
||||||
|
// 用途:
|
||||||
|
// - 前端传入 start_id/current_id/id,从该 ID 开始按 id 从小到大读取 Cursor Token。
|
||||||
|
// - 只读取未提取记录,不更新 is_extracted、extracted_time、extracted_platform、is_used 等任何状态。
|
||||||
|
// - 如果传入 ID 对应记录已提取,会自动跳过,继续找下一条未提取记录。
|
||||||
|
// - 返回 next_id,前端下一次点击时传 next_id,即可实现 11 -> 12 -> 13 递增读取。
|
||||||
|
//
|
||||||
|
// 示例:
|
||||||
|
//
|
||||||
|
// GET /api/cursor/token/peek?id=11
|
||||||
|
// GET /api/cursor/token/peek?start_id=11
|
||||||
|
// GET /api/cursor/token/peek?current_id=11
|
||||||
|
//
|
||||||
|
// 可选参数:
|
||||||
|
// - data_type=tk/account/account_tk,默认 tk
|
||||||
|
type ApiCursorDetectController struct {
|
||||||
|
beego.Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ApiCursorDetectController) cursorDetectJSONErr(httpStatus, code int, msg string) {
|
||||||
|
c.Ctx.Output.SetStatus(httpStatus)
|
||||||
|
c.Data["json"] = map[string]interface{}{
|
||||||
|
"code": code,
|
||||||
|
"msg": msg,
|
||||||
|
}
|
||||||
|
_ = c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeekToken 按 ID 顺序读取 Cursor Token,不改变任何状态。
|
||||||
|
func (c *ApiCursorDetectController) PeekToken() {
|
||||||
|
startID, err := c.readStartID()
|
||||||
|
if err != nil {
|
||||||
|
c.cursorDetectJSONErr(400, 400, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dataType := strings.TrimSpace(c.GetString("data_type"))
|
||||||
|
if dataType == "" {
|
||||||
|
dataType = "tk"
|
||||||
|
}
|
||||||
|
if !isValidPoolType(dataType) {
|
||||||
|
c.cursorDetectJSONErr(400, 400, "data_type 不合法,支持: account/tk/account_tk")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var row models.PlatformAccountPoolCursor
|
||||||
|
qs := models.Orm.QueryTable(new(models.PlatformAccountPoolCursor)).
|
||||||
|
Filter("id__gte", startID).
|
||||||
|
Filter("data_type", dataType).
|
||||||
|
Filter("delete_time__isnull", true).
|
||||||
|
Filter("extracted_time__isnull", true).
|
||||||
|
Filter("is_extracted", 0).
|
||||||
|
Exclude("token", "")
|
||||||
|
|
||||||
|
err = qs.OrderBy("id").One(&row)
|
||||||
|
if err != nil {
|
||||||
|
if err == orm.ErrNoRows {
|
||||||
|
c.cursorDetectJSONErr(404, 404, "从当前 ID 开始暂无未提取 Cursor Token")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.cursorDetectJSONErr(500, 500, "查询失败: "+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data["json"] = map[string]interface{}{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": map[string]interface{}{
|
||||||
|
"id": row.ID,
|
||||||
|
"next_id": row.ID + 1,
|
||||||
|
"data_type": row.DataType,
|
||||||
|
"account": row.Account,
|
||||||
|
"password": row.Password,
|
||||||
|
"token": row.Token,
|
||||||
|
"remark": row.Remark,
|
||||||
|
"is_used": row.IsUsed,
|
||||||
|
"create_time": row.CreateTime,
|
||||||
|
|
||||||
|
// 明确告诉前端:本接口只是读取,没有更新号池状态。
|
||||||
|
"state_changed": false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_ = c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ApiCursorDetectController) readStartID() (uint64, error) {
|
||||||
|
raw := strings.TrimSpace(c.GetString("id"))
|
||||||
|
if raw == "" {
|
||||||
|
raw = strings.TrimSpace(c.GetString("start_id"))
|
||||||
|
}
|
||||||
|
if raw == "" {
|
||||||
|
raw = strings.TrimSpace(c.GetString("current_id"))
|
||||||
|
}
|
||||||
|
if raw == "" {
|
||||||
|
return 0, fmt.Errorf("缺少参数 id/start_id/current_id")
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := strconv.ParseUint(raw, 10, 64)
|
||||||
|
if err != nil || id == 0 {
|
||||||
|
return 0, fmt.Errorf("id 必须是大于 0 的整数")
|
||||||
|
}
|
||||||
|
return id, nil
|
||||||
|
}
|
||||||
@ -2,6 +2,8 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"server/models"
|
"server/models"
|
||||||
@ -23,7 +25,7 @@ var validPlatformTypes = map[string]bool{
|
|||||||
"jingdong": true,
|
"jingdong": true,
|
||||||
"douyin": true,
|
"douyin": true,
|
||||||
"local": true,
|
"local": true,
|
||||||
"xubei": true,
|
"xubei": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// validModules 支持的号池模块
|
// validModules 支持的号池模块
|
||||||
@ -52,10 +54,16 @@ func (c *ApiGetCardController) cardOK(text string) {
|
|||||||
// - type (必填) 来源平台:xianyu / taobao / pinduoduo / jingdong / local / xubei
|
// - type (必填) 来源平台:xianyu / taobao / pinduoduo / jingdong / local / xubei
|
||||||
// - module (必填) 号池模块:cursor / windsurf / krio
|
// - module (必填) 号池模块:cursor / windsurf / krio
|
||||||
// - data_type (可选) 账号类型:account / tk / account_tk,不传则取任意未提取的
|
// - data_type (可选) 账号类型:account / tk / account_tk,不传则取任意未提取的
|
||||||
|
// - id/start_id/current_id (可选) 起始 ID:从该 ID 开始向后提取,避免传 896 却取到 892
|
||||||
func (c *ApiGetCardController) GetCard() {
|
func (c *ApiGetCardController) GetCard() {
|
||||||
platform := c.GetString("type")
|
platform := c.GetString("type")
|
||||||
module := c.GetString("module")
|
module := c.GetString("module")
|
||||||
dataType := c.GetString("data_type")
|
dataType := c.GetString("data_type")
|
||||||
|
startID, err := c.readOptionalStartID()
|
||||||
|
if err != nil {
|
||||||
|
c.cardErr(400, 400, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 参数校验
|
// 参数校验
|
||||||
if platform == "" {
|
if platform == "" {
|
||||||
@ -83,20 +91,42 @@ func (c *ApiGetCardController) GetCard() {
|
|||||||
|
|
||||||
switch module {
|
switch module {
|
||||||
case "cursor":
|
case "cursor":
|
||||||
c.extractCursor(platform, dataType, now)
|
c.extractCursor(platform, dataType, startID, now)
|
||||||
case "windsurf":
|
case "windsurf":
|
||||||
c.extractWindsurf(platform, dataType, now)
|
c.extractWindsurf(platform, dataType, startID, now)
|
||||||
case "krio":
|
case "krio":
|
||||||
c.extractKrio(platform, dataType, now)
|
c.extractKrio(platform, dataType, startID, now)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiGetCardController) extractCursor(platform, dataType string, now time.Time) {
|
func (c *ApiGetCardController) readOptionalStartID() (uint64, error) {
|
||||||
|
raw := strings.TrimSpace(c.GetString("id"))
|
||||||
|
if raw == "" {
|
||||||
|
raw = strings.TrimSpace(c.GetString("start_id"))
|
||||||
|
}
|
||||||
|
if raw == "" {
|
||||||
|
raw = strings.TrimSpace(c.GetString("current_id"))
|
||||||
|
}
|
||||||
|
if raw == "" {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := strconv.ParseUint(raw, 10, 64)
|
||||||
|
if err != nil || id == 0 {
|
||||||
|
return 0, fmt.Errorf("id/start_id/current_id 必须是大于 0 的整数")
|
||||||
|
}
|
||||||
|
return id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ApiGetCardController) extractCursor(platform, dataType string, startID uint64, now time.Time) {
|
||||||
c.extractWithProbe("cursor", platform, dataType, now, func() (uint64, *string, *string, string, string, *int8, error) {
|
c.extractWithProbe("cursor", platform, dataType, now, func() (uint64, *string, *string, string, string, *int8, error) {
|
||||||
var row models.PlatformAccountPoolCursor
|
var row models.PlatformAccountPoolCursor
|
||||||
qs := models.Orm.QueryTable(new(models.PlatformAccountPoolCursor)).
|
qs := models.Orm.QueryTable(new(models.PlatformAccountPoolCursor)).
|
||||||
Filter("is_extracted", 0).
|
Filter("is_extracted", 0).
|
||||||
Filter("delete_time__isnull", true)
|
Filter("delete_time__isnull", true)
|
||||||
|
if startID > 0 {
|
||||||
|
qs = qs.Filter("id__gte", startID)
|
||||||
|
}
|
||||||
if dataType != "" {
|
if dataType != "" {
|
||||||
qs = qs.Filter("data_type", dataType)
|
qs = qs.Filter("data_type", dataType)
|
||||||
}
|
}
|
||||||
@ -107,12 +137,15 @@ func (c *ApiGetCardController) extractCursor(platform, dataType string, now time
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiGetCardController) extractWindsurf(platform, dataType string, now time.Time) {
|
func (c *ApiGetCardController) extractWindsurf(platform, dataType string, startID uint64, now time.Time) {
|
||||||
c.extractWithProbe("windsurf", platform, dataType, now, func() (uint64, *string, *string, string, string, *int8, error) {
|
c.extractWithProbe("windsurf", platform, dataType, now, func() (uint64, *string, *string, string, string, *int8, error) {
|
||||||
var row models.PlatformAccountPoolWindsurf
|
var row models.PlatformAccountPoolWindsurf
|
||||||
qs := models.Orm.QueryTable(new(models.PlatformAccountPoolWindsurf)).
|
qs := models.Orm.QueryTable(new(models.PlatformAccountPoolWindsurf)).
|
||||||
Filter("is_extracted", 0).
|
Filter("is_extracted", 0).
|
||||||
Filter("delete_time__isnull", true)
|
Filter("delete_time__isnull", true)
|
||||||
|
if startID > 0 {
|
||||||
|
qs = qs.Filter("id__gte", startID)
|
||||||
|
}
|
||||||
if dataType != "" {
|
if dataType != "" {
|
||||||
qs = qs.Filter("data_type", dataType)
|
qs = qs.Filter("data_type", dataType)
|
||||||
}
|
}
|
||||||
@ -123,12 +156,15 @@ func (c *ApiGetCardController) extractWindsurf(platform, dataType string, now ti
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiGetCardController) extractKrio(platform, dataType string, now time.Time) {
|
func (c *ApiGetCardController) extractKrio(platform, dataType string, startID uint64, now time.Time) {
|
||||||
c.extractWithProbe("krio", platform, dataType, now, func() (uint64, *string, *string, string, string, *int8, error) {
|
c.extractWithProbe("krio", platform, dataType, now, func() (uint64, *string, *string, string, string, *int8, error) {
|
||||||
var row models.PlatformAccountPoolKiro
|
var row models.PlatformAccountPoolKiro
|
||||||
qs := models.Orm.QueryTable(new(models.PlatformAccountPoolKiro)).
|
qs := models.Orm.QueryTable(new(models.PlatformAccountPoolKiro)).
|
||||||
Filter("is_extracted", 0).
|
Filter("is_extracted", 0).
|
||||||
Filter("delete_time__isnull", true)
|
Filter("delete_time__isnull", true)
|
||||||
|
if startID > 0 {
|
||||||
|
qs = qs.Filter("id__gte", startID)
|
||||||
|
}
|
||||||
if dataType != "" {
|
if dataType != "" {
|
||||||
qs = qs.Filter("data_type", dataType)
|
qs = qs.Filter("data_type", dataType)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,10 @@ func Register() {
|
|||||||
// 登录器使用激活码激活/续期 Cursor 设备(无需登录)
|
// 登录器使用激活码激活/续期 Cursor 设备(无需登录)
|
||||||
beego.Router("/api/cursor/equipment/activateByCode", &controllers.ApiCursorEquipmentController{}, "post:ActivateByCode")
|
beego.Router("/api/cursor/equipment/activateByCode", &controllers.ApiCursorEquipmentController{}, "post:ActivateByCode")
|
||||||
|
|
||||||
|
// Cursor Token 顺序读取/检测接口(无需登录,不改变号池状态)
|
||||||
|
// GET /api/cursor/token/peek?id=11&data_type=tk
|
||||||
|
beego.Router("/api/cursor/token/peek", &controllers.ApiCursorDetectController{}, "get:PeekToken")
|
||||||
|
|
||||||
// 对外提卡接口(无需登录)
|
// 对外提卡接口(无需登录)
|
||||||
// GET /api/getcard?type=xianyu&module=cursor&data_type=tk
|
// GET /api/getcard?type=xianyu&module=cursor&data_type=tk
|
||||||
beego.Router("/api/getcard", &controllers.ApiGetCardController{}, "get:GetCard")
|
beego.Router("/api/getcard", &controllers.ApiGetCardController{}, "get:GetCard")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user