package api import ( "database/sql" "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{}{} 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 } m := map[string]interface{}{"id": id.Int64, "name": name.String} 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{}{} for rowsPlan.Next() { var id sql.NullInt64 var name sql.NullString if err := rowsPlan.Scan(&id, &name); err != nil { continue } if !id.Valid { continue } tmp = append(tmp, map[string]interface{}{"id": id.Int64, "name": name.String}) } 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] for rows2.Next() { var id sql.NullInt64 var name sql.NullString if err := rows2.Scan(&id, &name); err != nil { continue } if !id.Valid { continue } m := map[string]interface{}{"id": id.Int64, "name": name.String} out = append(out, m) } } } ok(w, r, out) }