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,63 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"mysql_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/answer/conf:go_default_library",
"//app/job/main/answer/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"account.go",
"bfs.go",
"dao.go",
"draw.go",
"mysql.go",
],
importpath = "go-common/app/job/main/answer/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/answer/conf:go_default_library",
"//app/job/main/answer/model: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/github.com/golang/freetype:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/golang.org/x/image/font:go_default_library",
"//vendor/golang.org/x/image/math/fixed: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,35 @@
package dao
import (
"context"
"fmt"
"net/url"
"strconv"
"go-common/library/log"
"github.com/pkg/errors"
)
const (
_wasFormal = -659
)
// BeFormal become a full member
func (d *Dao) BeFormal(c context.Context, mid int64, ip string) (err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
}
if err = d.xclient.Post(c, d.beFormal, ip, params, &res); err != nil {
err = errors.Wrapf(err, "beFormal url(%s)", d.beFormal+"?"+params.Encode())
return
}
if res.Code != 0 && res.Code != _wasFormal {
err = errors.WithStack(fmt.Errorf("beFormal(%d) failed(%v)", mid, res.Code))
return
}
log.Info("beFormal suc(%d) ", mid)
return
}

View File

@@ -0,0 +1,76 @@
package dao
import (
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"errors"
"fmt"
"hash"
"io"
"net/http"
"strconv"
"time"
"go-common/library/ecode"
"go-common/library/log"
)
var (
errUpload = errors.New("Upload failed")
)
// 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(d.c.BFS.Method, d.c.BFS.URL+filename, body)
if err != nil {
log.Error("http.NewRequest error (%v) | fileType(%s)", err, fileType)
return
}
expire := time.Now().Unix()
authorization := authorize(d.c.BFS.Key, d.c.BFS.Secret, d.c.BFS.Method, d.c.BFS.Bucket, filename, expire)
req.Header.Set("Host", d.c.BFS.Host)
req.Header.Add("Date", fmt.Sprint(expire))
req.Header.Add("Authorization", authorization)
req.Header.Add("Content-Type", fileType)
// timeout
ctx, cancel := context.WithTimeout(c, time.Duration(d.c.BFS.Timeout))
req = req.WithContext(ctx)
defer cancel()
resp, err := d.client.Do(req)
if err != nil {
log.Error("d.Client.Do error(%v) | url(%s)", err, d.c.BFS.URL+filename)
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.URL+filename)
err = errUpload
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.URL+filename)
err = errUpload
return
}
location = header.Get("Location")
return
}
// authorize returns authorization for upload file to bfs
func authorize(key, secret, method, bucket string, fname 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, fname, 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,51 @@
package dao
import (
"context"
"net/http"
"time"
"go-common/app/job/main/answer/conf"
"go-common/library/database/sql"
xhttp "go-common/library/net/http/blademaster"
)
const (
_bfsTimeout = 5 * time.Second
_beFormal = "/api/internal/member/beFormal"
)
// Dao event dao def.
type Dao struct {
c *conf.Config
db *sql.DB
client *http.Client
xclient *xhttp.Client
beFormal string
}
// New create instance of dao and return.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
db: sql.NewMySQL(c.Mysql),
client: &http.Client{
Timeout: _bfsTimeout,
},
xclient: xhttp.NewClient(c.HTTPClient),
beFormal: c.Properties.AccountIntranetURI + _beFormal,
}
return
}
// Ping check db health.
func (d *Dao) Ping(c context.Context) (err error) {
return d.db.Ping(c)
}
// Close close all db connections.
func (d *Dao) Close() {
if d.db != nil {
d.db.Close()
}
}

View File

@@ -0,0 +1,36 @@
package dao
import (
"flag"
"go-common/app/job/main/answer/conf"
"os"
"testing"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "")
flag.Set("conf_appid", "")
flag.Set("conf_token", "")
flag.Set("tree_id", "")
flag.Set("conf_version", "server-1")
flag.Set("deploy_env", "dev")
flag.Set("conf_env", "10")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../cmd/answer-job-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
os.Exit(m.Run())
}

View File

@@ -0,0 +1,130 @@
package dao
import (
"image"
"image/draw"
"io/ioutil"
"math"
"unicode/utf8"
"go-common/library/log"
"github.com/golang/freetype"
"golang.org/x/image/font"
"golang.org/x/image/math/fixed"
)
// TextImgConf text img conf.
type TextImgConf struct {
Fontsize int
Length int
Ansfontsize int
Spacing float64
Ansspacing float64
}
// QueConf question img conf.
func (d *Dao) QueConf(mobile bool) (c *TextImgConf) {
if mobile {
// Mobile
c = &TextImgConf{
Fontsize: 16, // mobile font size in points
Length: 11, // mobile question length
Ansfontsize: 12, // mobile ans font size in points
}
} else {
// PC
c = &TextImgConf{
Fontsize: 12, //font size in points
Length: 36, //question length
Ansfontsize: 10, //ans font size in points
}
}
c.Spacing = 2 // line spacing (e.g. 2 means double spaced)
c.Ansspacing = 2 // line ansspacing (e.g. 2 means double spaced)
return
}
// DrawQue draw question title.
func (d *Dao) DrawQue(c *freetype.Context, s string, conf *TextImgConf, pt *fixed.Point26_6) {
c.SetFontSize(float64(conf.Fontsize))
srune := []rune(s)
var end = conf.Length
for len(srune) > 0 {
if conf.Length > len(srune) {
end = len(srune)
}
d.text(c, string(srune[:end]), pt, conf.Fontsize, conf.Spacing)
srune = srune[end:]
}
}
// DrawAns draw ans
func (d *Dao) DrawAns(c *freetype.Context, conf *TextImgConf, anss [2]string, pt *fixed.Point26_6) {
c.SetFontSize(float64(conf.Ansfontsize))
arr := [4]string{"A.", "B."}
for i, a := range anss {
d.text(c, arr[i]+a, pt, conf.Ansfontsize, conf.Ansspacing)
}
}
// Board init draw board.
func (d *Dao) Board(h int) (r *image.Gray) {
bg := image.White
r = image.NewGray(image.Rect(0, 0, 600, h))
draw.Draw(r, r.Bounds(), bg, image.ZP, draw.Src)
return
}
//Height get img height
func (d *Dao) Height(c *TextImgConf, que string, anslen int) (h int) {
len := utf8.RuneCountInString(que)
line := math.Ceil(float64(len) / float64(c.Length))
h = int(math.Ceil(c.Spacing*line*float64(c.Fontsize))) + int(math.Ceil(c.Ansspacing*float64(anslen)*float64(c.Ansfontsize)))
return
}
// text Draw text.
func (d *Dao) text(c *freetype.Context, s string, pt *fixed.Point26_6, size int, spacing float64) (err error) {
_, err = c.DrawString(s, *pt)
if err != nil {
log.Error("c.DrawString() error:%+v", err)
return
}
pt.Y += fixed.Int26_6(int(float64(size)*spacing) << 6)
return
}
var (
dpi = float64(72) // screen resolution in Dots Per Inch
hinting = "none" // none | full
)
// Context freetype init context.
func (d *Dao) Context(r *image.Gray, fileStr string) (c *freetype.Context) {
fg := image.Black
// Read the font data.
fontBytes, err := ioutil.ReadFile(fileStr)
if err != nil {
log.Error("ioutil.ReadFile(%s) error:%+v", fileStr, err)
return
}
f, err := freetype.ParseFont(fontBytes)
if err != nil {
log.Error("freetype.ParseFont(%s) error:%+v", fileStr, err)
return
}
c = freetype.NewContext()
c.SetDPI(dpi)
c.SetFont(f)
c.SetClip(r.Bounds())
c.SetDst(r)
c.SetSrc(fg)
switch hinting {
default:
c.SetHinting(font.HintingNone)
case "full":
c.SetHinting(font.HintingFull)
}
return
}

View File

@@ -0,0 +1,77 @@
package dao
import (
"context"
"go-common/app/job/main/answer/model"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_questionByIDSQL = "SELECT mid,question,ans,status FROM answer_extra_question WHERE id=?"
_insQsSQL = "INSERT INTO answer_extra_question(question,ans,av_id,status,source,state,origin_id) VALUES(?,?,?,?,?,?,?)"
_updateQsSQL = "UPDATE answer_extra_question SET ans=?,status=?,isdel=? WHERE origin_id=?"
_questionExtraTypeSQL = "SELECT origin_id,ans,question,av_id,status,source FROM answer_extra_question WHERE isdel=1 and state=0 LIMIT ?"
_updateStateSQL = "UPDATE answer_extra_question SET state=? WHERE origin_id=?"
)
// ByID get question by id.
func (d *Dao) ByID(c context.Context, id int64) (que *model.LabourQs, err error) {
var row = d.db.QueryRow(c, _questionByIDSQL, id)
que = new(model.LabourQs)
if err = row.Scan(&que.Mid, &que.Question, &que.Ans, &que.Status); err != nil {
if err == sql.ErrNoRows {
que = nil
err = nil
return
}
log.Error("row.Scan() error(%v)", err)
}
return
}
// AddQs add labour question log.
func (d *Dao) AddQs(c context.Context, qs *model.LabourQs) (err error) {
if _, err = d.db.Exec(c, _insQsSQL, qs.Question, qs.Ans, qs.AvID, qs.Status, qs.Source, qs.State, qs.ID); err != nil {
log.Error("AddQs: db.Exec(as:%v) error(%v)", qs, err)
}
return
}
// UpdateQs update question.
func (d *Dao) UpdateQs(c context.Context, que *model.LabourQs) (err error) {
if _, err = d.db.Exec(c, _updateQsSQL, que.Ans, que.Status, que.Isdel, que.ID); err != nil {
log.Error("setQs: db.Exec(%v) error(%v)", que, err)
}
return
}
// QidsExtraByState get extra question ids by check
func (d *Dao) QidsExtraByState(c context.Context, size int) (res []*model.LabourQs, err error) {
var rows *sql.Rows
if rows, err = d.db.Query(c, _questionExtraTypeSQL, size); err != nil {
log.Error("d._questionExtraTypeSQL.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
r := new(model.LabourQs)
if err = rows.Scan(&r.ID, &r.Ans, &r.Question, &r.AvID, &r.Status, &r.Source); err != nil {
log.Error("row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
err = rows.Err()
return
}
// UpdateState update state.
func (d *Dao) UpdateState(c context.Context, que *model.LabourQs) (err error) {
if _, err = d.db.Exec(c, _updateStateSQL, que.State, que.ID); err != nil {
log.Error("UpdateState: db.Exec(%v) error(%v)", que, err)
}
return
}

View File

@@ -0,0 +1,62 @@
package dao
import (
"context"
"fmt"
"testing"
"go-common/app/job/main/answer/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestAddQue(t *testing.T) {
Convey("TestAddQue add question data", t, func() {
for i := 0; i < 10; i++ {
que := &model.LabourQs{
Question: fmt.Sprintf("测试d=====( ̄▽ ̄*)b厉害 %d", i),
Ans: int8(i%2 + 1),
AvID: int64(i),
Status: int8(i%2 + 1),
Source: 1,
State: model.HadCreateImg,
ID: int64(i),
}
err := d.AddQs(context.TODO(), que)
So(err, ShouldBeNil)
}
})
}
func TestUpdateState(t *testing.T) {
Convey("TestUpdateState", t, func() {
for i := 0; i < 10; i++ {
que := &model.LabourQs{
Question: fmt.Sprintf("测试d=====( ̄▽ ̄*)b厉害 %d", i),
Ans: int8(i%2 + 1),
AvID: int64(i),
Status: int8(i%2 + 1),
Source: 1,
State: model.HadCreateImg,
ID: int64(i),
}
err := d.UpdateState(context.TODO(), que)
So(err, ShouldBeNil)
}
})
}
func TestByID(t *testing.T) {
Convey("TestByID", t, func() {
res, err := d.ByID(context.TODO(), 1)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestBeFormal(t *testing.T) {
Convey("TestBeFormal", t, func() {
err := d.BeFormal(context.TODO(), 7593623, "127.0.0.1")
So(err, ShouldNotBeNil)
})
}