Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"mysql_test.go",
"redis_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = [
"bfs.go",
"dao.go",
"image.go",
"mysql.go",
"redis.go",
"season_es.go",
],
importpath = "go-common/app/admin/openplatform/sug/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/openplatform/sug/conf:go_default_library",
"//app/admin/openplatform/sug/model:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//vendor/code.google.com/p/graphics-go/graphics:go_default_library",
"//vendor/github.com/golang/freetype:go_default_library",
"//vendor/golang.org/x/image/font:go_default_library",
"//vendor/golang.org/x/image/math/fixed:go_default_library",
"//vendor/gopkg.in/olivere/elastic.v5:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,72 @@
package dao
import (
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"fmt"
"hash"
"io"
"net/http"
"strconv"
"time"
"go-common/library/ecode"
"go-common/library/log"
)
const _method = "PUT"
// Upload upload bfs.
func (d *Dao) Upload(c context.Context, fileType string, fileName string, body io.Reader) (location string, err error) {
req, err := http.NewRequest(_method, d.c.Bfs.Addr+fileName, body)
if err != nil {
log.Error("http.NewRequest error (%v) | fileType(%s) body(%v)", err, fileType, body)
return
}
expire := time.Now().Unix()
authorization := authorize(d.c.Bfs.Key, d.c.Bfs.Secret, _method, d.c.Bfs.Bucket, fileName, expire)
req.Header.Set("Host", d.c.Bfs.Addr)
req.Header.Add("Date", fmt.Sprint(expire))
req.Header.Add("Authorization", authorization)
req.Header.Add("Content-Type", fileType)
// timeout
c, cancel := context.WithTimeout(c, time.Duration(d.c.Bfs.Timeout))
req = req.WithContext(c)
defer cancel()
resp, err := d.client.Do(req)
if err != nil {
log.Error("d.Client.Do error(%v) | _url(%s) req(%v)", err, d.c.Bfs.Addr, req)
err = ecode.BfsUploadServiceUnavailable
return
}
if resp.StatusCode != http.StatusOK {
log.Error("Upload http.StatusCode nq http.StatusOK (%d) | url(%s)", resp.StatusCode, d.c.Bfs.Addr)
err = ecode.BfsUploadStatusErr
return
}
header := resp.Header
code := header.Get("Code")
if code != strconv.Itoa(http.StatusOK) {
log.Error("strconv.Itoa err, code(%s) | url(%s)", code, d.c.Bfs.Addr)
err = ecode.BfsUploadCodeErr
return
}
location = header.Get("Location")
return
}
func authorize(key, secret, method, bucket string, fileName string, expire int64) (authorization string) {
var (
content string
mac hash.Hash
signature string
)
content = fmt.Sprintf("%s\n%s\n%s\n%d\n", method, bucket, fileName, expire)
mac = hmac.New(sha1.New, []byte(secret))
mac.Write([]byte(content))
signature = base64.StdEncoding.EncodeToString(mac.Sum(nil))
authorization = fmt.Sprintf("%s:%s:%d", key, signature, expire)
return
}

View File

@@ -0,0 +1,85 @@
package dao
import (
"context"
"net/http"
"time"
"go-common/app/admin/openplatform/sug/conf"
"go-common/library/cache/redis"
"go-common/library/database/sql"
"go-common/library/log"
xhttp "go-common/library/net/http/blademaster"
elastic "gopkg.in/olivere/elastic.v5"
)
// Dao dao
type Dao struct {
c *conf.Config
redis *redis.Pool
es *elastic.Client
client *http.Client
xclient *xhttp.Client
dbMall *sql.DB
dbTicket *sql.DB
}
// New init redis,es
func New(c *conf.Config) (dao *Dao) {
dao = &Dao{
c: c,
redis: redis.NewPool(c.Redis),
xclient: xhttp.NewClient(c.HTTPClient),
client: &http.Client{Timeout: time.Second * 5},
dbMall: sql.NewMySQL(c.DB.MallDB),
dbTicket: sql.NewMySQL(c.DB.TicketDB),
}
es, err := elastic.NewClient(
elastic.SetURL(c.Es.Addr...),
)
if err != nil {
panic(err)
}
dao.es = es
return
}
// Close close the resource.
func (d *Dao) Close() {
d.redis.Close()
}
// Ping dao ping
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.dbTicket.Ping(c); err != nil {
log.Error("Ping ticket DB error(%v)", err)
return
}
if err = d.dbMall.Ping(c); err != nil {
log.Error("Ping mall DB error(%v)", err)
return
}
if err = d.pingESCluster(c); err != nil {
log.Error("es:ping", "ping %v", err)
return
}
redisConn := d.redis.Get(c)
defer redisConn.Close()
if _, err = redisConn.Do("SET", "ping", "pong"); err != nil {
redisConn.Close()
log.Error("redis.SET error(%v)", err)
return
}
return
}
// pingEsCluster ping es cluster
func (d *Dao) pingESCluster(ctx context.Context) (err error) {
_, _, err = d.es.Ping(d.c.Es.Addr[0]).Do(ctx)
if err != nil {
log.Error("Es:Ping", "%s:Ping error(%v)", d.c.Es.Addr[0], err)
return
}
return
}

View File

@@ -0,0 +1,156 @@
package dao
import (
"bufio"
"bytes"
"context"
"fmt"
"go-common/app/admin/openplatform/sug/model"
"go-common/library/log"
"image"
"image/color"
"image/draw"
"image/jpeg"
"image/png"
"io/ioutil"
"net/http"
"os"
"regexp"
"code.google.com/p/graphics-go/graphics"
"github.com/golang/freetype"
"golang.org/x/image/font"
"golang.org/x/image/math/fixed"
)
const (
_Width = 1125
_Height = 234
_HeaderLength = 168
)
var (
_RGBA = []int{244, 245, 247, 255}
_HeadArea = []int{36, 33, 204, 201}
_LabelArea = []int{234, 156, 348, 201}
_BriefText = []int{234, 72}
_NameText = []int{234, 129}
_BriefSize = 44
_NameSize = 36
_BriefRGBA = []int{33, 33, 33, 255}
_NameRGBA = []int{153, 153, 153, 255}
_BriefLimit = 1000
_NameLimit = 1000
)
// CreateItemPNG make a pic for sug
func (d *Dao) CreateItemPNG(item model.Item) (location string, err error) {
var r *image.NRGBA64
if r, err = d.makeBoard(item.Img); err != nil {
log.Error("Create picture board error(%v)", err)
return
}
if item.Brief == "" {
item.Brief = item.Name
}
r = d.drawText(r, item.Brief, item.Name)
buf := new(bytes.Buffer)
png.Encode(buf, r)
bufReader := bufio.NewReader(buf)
if location, err = d.Upload(context.TODO(), "image/png", fmt.Sprintf("season_sug_%s/%d.png", d.c.Env, item.ItemsID), bufReader); err != nil {
log.Error("Upload pic png error (%v)", err)
return
}
reg, _ := regexp.CompilePOSIX(`//(.*)+`)
location = reg.FindString(location)
return
}
func (d *Dao) makeBoard(headerURL string) (board *image.NRGBA64, err error) {
var header image.Image
radius, _ := os.Open(d.c.SourcePath + "radius.png")
label, _ := os.Open(d.c.SourcePath + "label.png")
defer radius.Close()
defer label.Close()
resp, err := http.Get("http:" + headerURL)
bs, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Error("ioutil.ReadAll img error(%v)", err)
return
}
imgType := http.DetectContentType(bs)
buf := bytes.NewBuffer(bs)
resp.Body = ioutil.NopCloser(buf)
if err != nil {
log.Error("http download head img error(%v)", err)
return
}
defer resp.Body.Close()
switch imgType {
case "image/png":
header, err = png.Decode(resp.Body)
if err != nil {
log.Error("png picture decode error(%v)", err)
return
}
case "image/jpeg", "image/jpg":
header, err = jpeg.Decode(resp.Body)
if err != nil {
log.Error("jpg picture decode err(%v)", err)
return
}
default:
log.Error("invaild picture type (%s)", headerURL)
return
}
board = image.NewNRGBA64(image.Rect(0, 0, _Width, _Height))
draw.Draw(board, board.Bounds(), image.White, image.ZP, draw.Src)
radiusPNG, _ := png.Decode(radius)
cover := image.NewRGBA64(image.Rect(0, 0, _HeaderLength, _HeaderLength))
border := image.NewNRGBA64(image.Rect(0, 0, _HeaderLength, _HeaderLength))
headBoard := image.NewRGBA64(image.Rect(0, 0, _HeaderLength, _HeaderLength))
draw.Draw(headBoard, headBoard.Bounds(), image.NewUniform(color.NRGBA{uint8(_RGBA[0]), uint8(_RGBA[1]), uint8(_RGBA[2]), uint8(_RGBA[3])}), image.ZP, draw.Over)
graphics.Thumbnail(border, radiusPNG)
graphics.Thumbnail(cover, header)
labelPNG, _ := png.Decode(label)
draw.Draw(headBoard, headBoard.Bounds(), cover, image.ZP, draw.Over)
draw.Draw(headBoard, headBoard.Bounds(), border, image.ZP, draw.Over)
draw.Draw(board, image.Rect(_HeadArea[0], _HeadArea[1], _HeadArea[2], _HeadArea[3]), headBoard, image.ZP, draw.Over)
draw.Draw(board, image.Rect(_LabelArea[0], _LabelArea[1], _LabelArea[2], _LabelArea[3]), labelPNG, image.ZP, draw.Over)
return
}
func (d *Dao) drawText(r *image.NRGBA64, brief string, name string) *image.NRGBA64 {
ptBrief := fixed.P(_BriefText[0], _BriefText[1])
ptName := fixed.P(_NameText[0], _NameText[1])
freetypeC := d.Context(r)
d.Text(freetypeC, brief, &ptBrief, _BriefSize, image.NewUniform(color.NRGBA{uint8(_BriefRGBA[0]), uint8(_BriefRGBA[1]), uint8(_BriefRGBA[2]), uint8(_BriefRGBA[3])}), fixed.I(_BriefLimit))
d.Text(freetypeC, name, &ptName, _NameSize, image.NewUniform(color.NRGBA{uint8(_NameRGBA[0]), uint8(_NameRGBA[1]), uint8(_NameRGBA[2]), uint8(_RGBA[3])}), fixed.I(_NameLimit))
return r
}
// Context get font for drawing
func (d *Dao) Context(r *image.NRGBA64) (c *freetype.Context) {
c = freetype.NewContext()
c.SetClip(r.Bounds())
c.SetDst(r)
c.SetHinting(font.HintingNone)
return
}
// Text draw letters on pic
func (d *Dao) Text(c *freetype.Context, s string, pt *fixed.Point26_6, size int, color image.Image, length fixed.Int26_6) (err error) {
c.SetFontSize(float64(size))
c.SetSrc(color)
ttf, _ := ioutil.ReadFile(d.c.SourcePath + "font.ttf")
font, _ := freetype.ParseFont(ttf)
c.SetFont(font)
for _, r := range s {
c.DrawString(string(r), *pt)
pt.X += font.HMetric(fixed.Int26_6(size*64), font.Index(r)).AdvanceWidth
if pt.X > length {
break
}
}
return
}

View File

@@ -0,0 +1,100 @@
package dao
import (
"context"
"fmt"
"encoding/json"
"go-common/app/admin/openplatform/sug/model"
"go-common/library/database/sql"
"go-common/library/log"
"time"
)
const (
_getItem = "SELECT `items_id`,`name`,`brief`,`img` FROM `items` WHERE `items_id` = ? AND `is_lastest_version` = 1"
_insertMatch = "INSERT INTO `sug_filter` (`season_id`,`items_id`,`type`,`sort`,`season_name`,`items_name`,`head_pic`,`sug_pic`) VALUE (?,?,?,?,?,?,?,?)"
_updateMatch = "UPDATE `sug_filter` SET `type` = ?,`season_name`=?,`items_name`=?,`sort`=?,`sug_pic`=? WHERE `season_id` = ? AND `items_id` = ?"
_matchExist = "SELECT `type` FROM `sug_filter` WHERE `season_id` = ? AND `items_id` = ?"
)
var _selectMatch = "SELECT `season_id`,`items_id`,`sort`,`season_name`,`items_name`,`head_pic`,`sug_pic` FROM `sug_filter` where type = 1"
// GetItem get mall items from db.
func (d *Dao) GetItem(c context.Context, itemsID int64) (item model.Item, err error) {
row := d.dbMall.QueryRow(c, _getItem, itemsID)
if err = row.Scan(&item.ItemsID, &item.Name, &item.Brief, &item.Img); err != nil {
log.Error("Get item %d error,err(%v)", itemsID, err)
return
}
if item.Brief == "" {
item.Brief = item.Name
item.Name = ""
}
var imgListArr []string
if err = json.Unmarshal([]byte(item.Img), &imgListArr); err != nil {
log.Error("get first img err[%s] (%v)", item.Img, err)
return
}
item.Img = imgListArr[0]
return
}
// UpdateMatch update match.
func (d *Dao) UpdateMatch(c context.Context, season model.Season, item model.Item, typeInt int8, sugPic string) (affect int64, err error) {
res, err := d.dbTicket.Exec(c, _updateMatch, typeInt, season.Title, item.Name, time.Now().Unix(), sugPic, season.ID, item.ItemsID)
if err != nil {
log.Error("row.exec error(%v)", err)
return
}
affect, err = res.RowsAffected()
return
}
// InsertMatch insert match.
func (d *Dao) InsertMatch(c context.Context, season model.Season, item model.Item, typeInt int8, sort int64, location string) (affect int64, err error) {
res, err := d.dbTicket.Exec(c, _insertMatch, season.ID, item.ItemsID, typeInt, sort, season.Title, item.Name, item.Img, location)
if err != nil {
log.Error("row.exec error(%v)", err)
return
}
affect, err = res.RowsAffected()
return
}
// GetMatchType get match type.
func (d *Dao) GetMatchType(c context.Context, seasonID, itemsID int64) (matchType int8, err error) {
row := d.dbTicket.QueryRow(c, _matchExist, seasonID, itemsID)
if err = row.Scan(&matchType); err != nil {
if err == sql.ErrNoRows {
return -1, nil
}
return
}
return
}
// SearchV2 search match from db
func (d *Dao) SearchV2(c context.Context, params *model.Search) (list []model.SugList, err error) {
var rows *sql.Rows
sqlStr := _selectMatch
if params.ItemsID > 0 {
sqlStr += fmt.Sprintf(" and items_id = %d", params.ItemsID)
}
if params.SeasonID > 0 {
sqlStr += fmt.Sprintf(" and season_id = %d", params.SeasonID)
}
if rows, err = d.dbTicket.Query(c, sqlStr); err != nil {
log.Error("d._selectMatchSQL.Query error(%v)", err)
return
}
for rows.Next() {
sug := new(model.SugList)
if err = rows.Scan(&sug.SeasonId, &sug.ItemsID, &sug.Score, &sug.SeasonName, &sug.ItemsName, &sug.PicURL, &sug.SugURL); err != nil {
log.Error("row.Scan() error(%v)", err)
continue
}
list = append(list, *sug)
}
return
}

View File

@@ -0,0 +1,19 @@
package dao
import "testing"
func TestDao_GetItem(t *testing.T) {
}
func TestDao_GetMatchType(t *testing.T) {
}
func TestDao_InsertMatch(t *testing.T) {
}
func TestDao_UpdateMatch(t *testing.T) {
}

View File

@@ -0,0 +1,74 @@
package dao
import (
"context"
"fmt"
//
"go-common/app/admin/openplatform/sug/model"
"go-common/library/cache/redis"
)
const (
_sugSeason = "SUG:SEASON:%d"
_sugItem = "SUGITEM:%d"
_expire = 93600
)
// SetSug set redis sug
func (d *Dao) SetSug(c context.Context, seasonID int64, ItemID int64, score int64) (err error) {
conn := d.redis.Get(c)
defer conn.Close()
key := fmt.Sprintf(_sugSeason, seasonID)
if err = conn.Send("ZADD", key, score, ItemID); err != nil {
return
}
if err = conn.Send("EXPIRE", key, _expire); err != nil {
return
}
if err = conn.Flush(); err != nil {
return
}
return
}
// DelSug del redis sug
func (d *Dao) DelSug(c context.Context, seasonID, itemsID int64) (err error) {
conn := d.redis.Get(c)
defer conn.Close()
if _, err = conn.Do("ZREM", fmt.Sprintf(_sugSeason, seasonID), itemsID); err != nil {
return
}
return
}
// SetItem set redis item
func (d *Dao) SetItem(c context.Context, item *model.Item, location string) (b bool, err error) {
conn := d.redis.Get(c)
defer conn.Close()
if err = conn.Send("HSET", fmt.Sprintf(_sugItem, item.ItemsID), "items_id", item.ItemsID); err != nil {
return
}
if err = conn.Send("HSET", fmt.Sprintf(_sugItem, item.ItemsID), "name", item.Name); err != nil {
return
}
if err = conn.Send("HSET", fmt.Sprintf(_sugItem, item.ItemsID), "brief", item.Brief); err != nil {
return
}
if err = conn.Send("HSET", fmt.Sprintf(_sugItem, item.ItemsID), "head", item.Img); err != nil {
return
}
if err = conn.Send("HSET", fmt.Sprintf(_sugItem, item.ItemsID), "pic", location); err != nil {
return
}
if err = conn.Send("EXPIRE", fmt.Sprintf(_sugItem, item.ItemsID), _expire); err != nil {
return
}
if err = conn.Flush(); err != nil {
return
}
if b, err = redis.Bool(conn.Receive()); err != nil {
return
}
conn.Receive()
return
}

View File

@@ -0,0 +1,19 @@
package dao
import "testing"
func TestDao_DelSug(t *testing.T) {
}
func TestDao_SetItem(t *testing.T) {
}
func TestDao_SetSug(t *testing.T) {
}
func TestDao_DelItem(t *testing.T) {
}

View File

@@ -0,0 +1,93 @@
package dao
import (
"bytes"
"context"
"encoding/json"
"fmt"
"strconv"
"go-common/app/admin/openplatform/sug/model"
"go-common/library/log"
"gopkg.in/olivere/elastic.v5"
"io/ioutil"
)
const (
_seasonIndex = "%s_sug_job_season"
_seasonType = "sug_job_season"
)
// GetSeason get season from es.
func (d *Dao) GetSeason(ctx context.Context, seasonID int64) (season model.Season, err error) {
seasonTermQuery := elastic.NewTermQuery("id", seasonID)
searchResult, err := d.es.Search().Index(fmt.Sprintf(_seasonIndex, d.c.Env)).Type(_seasonType).Query(seasonTermQuery).From(0).Size(1).Timeout("1s").Do(ctx)
if err != nil {
log.Error("es search error(%v)", err)
return
}
if searchResult.Hits.TotalHits > 0 {
for _, hit := range searchResult.Hits.Hits {
err = json.Unmarshal(*hit.Source, &season)
if err != nil {
log.Error("json.Unmarshal err(%v)", err)
return season, err
}
}
}
return
}
// SeasonList search season list.
func (d *Dao) SeasonList(ctx context.Context, params *model.SourceSearch) (list []model.Season, err error) {
query := elastic.NewBoolQuery()
matchQuery := elastic.NewMatchQuery("title", params.Keyword).Fuzziness("40")
sid, _ := strconv.Atoi(params.Keyword)
termQuery := elastic.NewMatchQuery("id", sid).Boost(100)
query.Should(matchQuery)
query.Should(termQuery)
searchResult, err := d.es.Search().Index(fmt.Sprintf(_seasonIndex, d.c.Env)).Type(_seasonType).Query(query).From(0).Size(10).Timeout("1s").Do(ctx)
if err != nil {
return
}
list = []model.Season{}
if searchResult.Hits.TotalHits > 0 {
var season model.Season
for _, hit := range searchResult.Hits.Hits {
err := json.Unmarshal(*hit.Source, &season)
if err != nil {
log.Error("json.Unmarshal error(%v)", err)
continue
}
list = append(list, season)
}
}
return
}
// ItemList mall items list from http.
func (d *Dao) ItemList(ctx context.Context, params *model.SourceSearch) (itemsList []model.Items, err error) {
query := make(map[string]interface{})
query["pageNum"] = params.PageNum
query["pageSize"] = params.PageSize
query["shopId"] = 0
query["keyword"] = params.Keyword
jsonQuery, _ := json.Marshal(query)
resp, err := d.client.Post(d.c.URL.ItemSearch, "application/json", bytes.NewReader(jsonQuery))
if err != nil {
log.Error("Request error(%v)", err)
return
}
HTTPResponse := model.HTTPResponse{}
bodyJSON, _ := ioutil.ReadAll(resp.Body)
if err = json.Unmarshal(bodyJSON, &HTTPResponse); err != nil {
log.Error("json.Unmarshal error(%v)", err)
}
if HTTPResponse.Code != 0 {
log.Error("Request (%s) search error(%v)", d.c.URL.ItemSearch, err)
return
}
itemsList = HTTPResponse.Data.List
return
}