88 lines
2.7 KiB
Go
88 lines
2.7 KiB
Go
package shared
|
||
|
||
import (
|
||
"context"
|
||
"database/sql"
|
||
"errors"
|
||
"fmt"
|
||
"strconv"
|
||
"strings"
|
||
)
|
||
|
||
var ErrInvalidUserIdentityFilter = errors.New("invalid user identity filter")
|
||
|
||
// ResolveExactUserID 把后台输入框里的用户身份解析成 owner service 使用的内部 user_id。
|
||
// 查询条件复用统一身份 SQL:精确长 ID、当前展示号、默认短号、active 靓号优先,昵称只做最后的模糊兜底。
|
||
func ResolveExactUserID(ctx context.Context, db *sql.DB, appCode string, keyword string, nowMs int64) (int64, bool, error) {
|
||
keyword = strings.TrimSpace(keyword)
|
||
if keyword == "" || db == nil {
|
||
return 0, false, nil
|
||
}
|
||
matchSQL, matchArgs := UserIdentityExactSQL("u", "u.user_id", keyword, nowMs)
|
||
orderSQL, orderArgs := UserIdentityExactOrderSQL("u", "u.user_id", keyword, nowMs)
|
||
args := append([]any{appCode}, matchArgs...)
|
||
args = append(args, orderArgs...)
|
||
row := db.QueryRowContext(ctx, `
|
||
SELECT u.user_id
|
||
FROM users u
|
||
WHERE u.app_code = ? AND `+matchSQL+`
|
||
ORDER BY
|
||
`+orderSQL+`,
|
||
u.user_id DESC
|
||
LIMIT 1`,
|
||
args...,
|
||
)
|
||
var userID int64
|
||
if err := row.Scan(&userID); err != nil {
|
||
if errors.Is(err, sql.ErrNoRows) {
|
||
return 0, false, nil
|
||
}
|
||
return 0, false, err
|
||
}
|
||
return userID, true, nil
|
||
}
|
||
|
||
func ResolveUserIdentityFilter(ctx context.Context, db *sql.DB, appCode string, filter UserIdentityFilter, nowMs int64) (int64, bool, error) {
|
||
if filter.IsEmpty() || db == nil {
|
||
return 0, false, nil
|
||
}
|
||
matchSQL, matchArgs := UserIdentityFieldsSQL("u", "u.user_id", filter, nowMs)
|
||
args := append([]any{appCode}, matchArgs...)
|
||
row := db.QueryRowContext(ctx, `
|
||
SELECT u.user_id
|
||
FROM users u
|
||
WHERE u.app_code = ? AND `+matchSQL+`
|
||
ORDER BY u.updated_at_ms DESC, u.user_id DESC
|
||
LIMIT 1`,
|
||
args...,
|
||
)
|
||
var userID int64
|
||
if err := row.Scan(&userID); err != nil {
|
||
if errors.Is(err, sql.ErrNoRows) {
|
||
return 0, false, nil
|
||
}
|
||
return 0, false, err
|
||
}
|
||
return userID, true, nil
|
||
}
|
||
|
||
// ResolveExactUserIDOrNumericFallback 用于列表 owner 在 wallet/activity 等下游服务的场景。
|
||
// 下游只认内部 user_id,后台先按短号/靓号解析;解析不到时只接受正整数长 ID,兼容用户资料缺失的历史事实记录。
|
||
func ResolveExactUserIDOrNumericFallback(ctx context.Context, db *sql.DB, appCode string, keyword string, nowMs int64) (int64, bool, error) {
|
||
keyword = strings.TrimSpace(keyword)
|
||
if keyword == "" {
|
||
return 0, false, nil
|
||
}
|
||
if db != nil {
|
||
userID, matched, err := ResolveExactUserID(ctx, db, appCode, keyword, nowMs)
|
||
if err != nil || matched {
|
||
return userID, matched, err
|
||
}
|
||
}
|
||
userID, err := strconv.ParseInt(keyword, 10, 64)
|
||
if err != nil || userID <= 0 {
|
||
return 0, true, fmt.Errorf("%w: %s", ErrInvalidUserIdentityFilter, keyword)
|
||
}
|
||
return userID, true, nil
|
||
}
|