155 lines
4.1 KiB
Go
155 lines
4.1 KiB
Go
package controllers
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"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 对应的 Cursor Token。
|
|
// - 只读取记录,不更新 is_extracted、extracted_time、extracted_platform、is_used 等任何状态。
|
|
// - 不再跳过已提取的记录,输入什么 ID 就提取什么 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()
|
|
}
|
|
|
|
func (c *ApiCursorDetectController) setTokenUsableByID(isUsed int8) {
|
|
id, err := c.readStartID()
|
|
if err != nil {
|
|
c.cursorDetectJSONErr(400, 400, err.Error())
|
|
return
|
|
}
|
|
|
|
now := time.Now()
|
|
updated, err := models.Orm.QueryTable(new(models.PlatformAccountPoolCursor)).
|
|
Filter("id", id).
|
|
Filter("delete_time__isnull", true).
|
|
Update(orm.Params{
|
|
"is_used": isUsed,
|
|
"update_time": now,
|
|
})
|
|
if err != nil {
|
|
c.cursorDetectJSONErr(500, 500, "更新失败: "+err.Error())
|
|
return
|
|
}
|
|
if updated == 0 {
|
|
c.cursorDetectJSONErr(404, 404, "当前 ID 数据不存在或已删除")
|
|
return
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{
|
|
"code": 200,
|
|
"msg": "success",
|
|
"data": map[string]interface{}{
|
|
"id": id,
|
|
"is_used": isUsed,
|
|
"is_available": isUsed == 1,
|
|
"state_changed": true,
|
|
"update_time": now,
|
|
},
|
|
}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
// MarkTokenAvailable 将当前 ID 的 Cursor Token 标记为可用。
|
|
func (c *ApiCursorDetectController) MarkTokenAvailable() {
|
|
c.setTokenUsableByID(1)
|
|
}
|
|
|
|
// MarkTokenUnavailable 将当前 ID 的 Cursor Token 标记为不可用/用完。
|
|
func (c *ApiCursorDetectController) MarkTokenUnavailable() {
|
|
c.setTokenUsableByID(0)
|
|
}
|
|
|
|
// PeekToken 按 ID 顺序读取 Cursor Token,不改变任何状态。
|
|
func (c *ApiCursorDetectController) PeekToken() {
|
|
startID, err := c.readStartID()
|
|
if err != nil {
|
|
c.cursorDetectJSONErr(400, 400, err.Error())
|
|
return
|
|
}
|
|
|
|
var row models.PlatformAccountPoolCursor
|
|
qs := models.Orm.QueryTable(new(models.PlatformAccountPoolCursor)).
|
|
Filter("id", startID).
|
|
Filter("delete_time__isnull", true).
|
|
Exclude("token", "")
|
|
|
|
err = qs.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
|
|
}
|