159 lines
3.9 KiB
Go
159 lines
3.9 KiB
Go
package api
|
||
|
||
import (
|
||
"database/sql"
|
||
"fmt"
|
||
"net/http"
|
||
"strconv"
|
||
"strings"
|
||
)
|
||
|
||
type CreatorsAPI struct {
|
||
marketing *sql.DB
|
||
}
|
||
|
||
func CreatorsHandler(marketing *sql.DB) http.Handler {
|
||
api := &CreatorsAPI{marketing: marketing}
|
||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
p := strings.TrimPrefix(r.URL.Path, "/api/creators")
|
||
if r.Method == http.MethodGet && p == "" {
|
||
api.list(w, r)
|
||
return
|
||
}
|
||
w.WriteHeader(http.StatusNotFound)
|
||
})
|
||
}
|
||
|
||
func (a *CreatorsAPI) list(w http.ResponseWriter, r *http.Request) {
|
||
q := r.URL.Query().Get("q")
|
||
limitStr := r.URL.Query().Get("limit")
|
||
limit := 2000
|
||
if limitStr != "" {
|
||
if n, err := strconv.Atoi(limitStr); err == nil && n > 0 && n <= 10000 {
|
||
limit = n
|
||
}
|
||
}
|
||
sql1 := "SELECT DISTINCT user_id, COALESCE(user_name, '') AS name FROM activity WHERE user_id IS NOT NULL"
|
||
args := []interface{}{}
|
||
if q != "" {
|
||
sql1 += " AND (CAST(user_id AS CHAR) LIKE ? OR user_name LIKE ?)"
|
||
like := "%" + q + "%"
|
||
args = append(args, like, like)
|
||
}
|
||
sql1 += " ORDER BY user_id ASC LIMIT ?"
|
||
args = append(args, limit)
|
||
rows, err := a.marketing.Query(sql1, args...)
|
||
out := []map[string]interface{}{}
|
||
used := map[int64]struct{}{}
|
||
if err == nil {
|
||
defer rows.Close()
|
||
for rows.Next() {
|
||
var id sql.NullInt64
|
||
var name sql.NullString
|
||
if err := rows.Scan(&id, &name); err != nil {
|
||
continue
|
||
}
|
||
if !id.Valid {
|
||
continue
|
||
}
|
||
if _, ok := used[id.Int64]; ok {
|
||
continue
|
||
}
|
||
used[id.Int64] = struct{}{}
|
||
|
||
n := strings.TrimSpace(name.String)
|
||
if n == "" {
|
||
n = strconv.FormatInt(id.Int64, 10)
|
||
}
|
||
display := fmt.Sprintf("%s(%d)", n, id.Int64)
|
||
|
||
m := map[string]interface{}{"id": id.Int64, "name": display}
|
||
out = append(out, m)
|
||
}
|
||
}
|
||
if err != nil || len(out) == 0 {
|
||
sqlPlan := "SELECT DISTINCT creator, COALESCE(creator_name, '') AS name FROM plan WHERE creator IS NOT NULL"
|
||
argsPlan := []interface{}{}
|
||
if q != "" {
|
||
sqlPlan += " AND (CAST(creator AS CHAR) LIKE ? OR creator_name LIKE ?)"
|
||
like := "%" + q + "%"
|
||
argsPlan = append(argsPlan, like, like)
|
||
}
|
||
sqlPlan += " ORDER BY creator ASC LIMIT ?"
|
||
argsPlan = append(argsPlan, limit)
|
||
rowsPlan, errPlan := a.marketing.Query(sqlPlan, argsPlan...)
|
||
if errPlan == nil {
|
||
defer rowsPlan.Close()
|
||
tmp := []map[string]interface{}{}
|
||
usedPlan := map[int64]struct{}{}
|
||
for rowsPlan.Next() {
|
||
var id sql.NullInt64
|
||
var name sql.NullString
|
||
if err := rowsPlan.Scan(&id, &name); err != nil {
|
||
continue
|
||
}
|
||
if !id.Valid {
|
||
continue
|
||
}
|
||
if _, ok := usedPlan[id.Int64]; ok {
|
||
continue
|
||
}
|
||
usedPlan[id.Int64] = struct{}{}
|
||
|
||
n := strings.TrimSpace(name.String)
|
||
if n == "" {
|
||
n = strconv.FormatInt(id.Int64, 10)
|
||
}
|
||
display := fmt.Sprintf("%s(%d)", n, id.Int64)
|
||
|
||
tmp = append(tmp, map[string]interface{}{"id": id.Int64, "name": display})
|
||
}
|
||
if len(tmp) > 0 {
|
||
out = tmp
|
||
}
|
||
}
|
||
if len(out) == 0 {
|
||
sql2 := "SELECT DISTINCT creator, '' AS name FROM `order` WHERE creator IS NOT NULL"
|
||
args2 := []interface{}{}
|
||
if q != "" {
|
||
sql2 += " AND CAST(creator AS CHAR) LIKE ?"
|
||
args2 = append(args2, "%"+q+"%")
|
||
}
|
||
sql2 += " ORDER BY creator ASC LIMIT ?"
|
||
args2 = append(args2, limit)
|
||
rows2, err2 := a.marketing.Query(sql2, args2...)
|
||
if err2 != nil {
|
||
fail(w, r, http.StatusInternalServerError, err2.Error())
|
||
return
|
||
}
|
||
defer rows2.Close()
|
||
out = out[:0]
|
||
usedOrder := map[int64]struct{}{}
|
||
for rows2.Next() {
|
||
var id sql.NullInt64
|
||
var name sql.NullString
|
||
if err := rows2.Scan(&id, &name); err != nil {
|
||
continue
|
||
}
|
||
if !id.Valid {
|
||
continue
|
||
}
|
||
if _, ok := usedOrder[id.Int64]; ok {
|
||
continue
|
||
}
|
||
usedOrder[id.Int64] = struct{}{}
|
||
|
||
n := strings.TrimSpace(name.String)
|
||
if n == "" {
|
||
n = strconv.FormatInt(id.Int64, 10)
|
||
}
|
||
display := fmt.Sprintf("%s(%d)", n, id.Int64)
|
||
|
||
m := map[string]interface{}{"id": id.Int64, "name": display}
|
||
out = append(out, m)
|
||
}
|
||
}
|
||
}
|
||
ok(w, r, out)
|
||
}
|