diff --git a/api_join.go b/api_join.go index e6882f1..728b960 100644 --- a/api_join.go +++ b/api_join.go @@ -13,8 +13,6 @@ func Follow(event *linebot.Event) { } Hit("加入", uid) - reply := event.ReplyToken - row := DB.Exec("select id from users where id = ?", uid).RowsAffected if row == 0 { // 新用戶 @@ -23,31 +21,18 @@ func Follow(event *linebot.Event) { return } - // 舊用戶 log.Debug().Str("user", uid).Msg("New user.") msg := linebot.NewTextMessage("你好!") - if reply != "" { - if _, err := bot.ReplyMessage(reply, msg).Do(); err != nil { - log.Error().Err(err).Caller().Msg("reply error") - } - } else { - if _, err := bot.PushMessage(uid, msg).Do(); err != nil { - log.Error().Err(err).Caller().Msg("push error") - } + if _, err := SendMessage(event.ReplyToken, uid, msg); err != nil { + panic(err) } } else { // 舊用戶 log.Debug().Str("user", uid).Msg("user unblocked.") msg := linebot.NewTextMessage("歡迎回來!") - if reply != "" { - if _, err := bot.ReplyMessage(reply, msg).Do(); err != nil { - log.Error().Err(err).Caller().Msg("reply error") - } - } else { - if _, err := bot.PushMessage(uid, msg).Do(); err != nil { - log.Error().Err(err).Caller().Msg("push error") - } + if _, err := SendMessage(event.ReplyToken, uid, msg); err != nil { + panic(err) } } diff --git a/setup_line.go b/api_line.go similarity index 80% rename from setup_line.go rename to api_line.go index fa05972..270d017 100644 --- a/setup_line.go +++ b/api_line.go @@ -9,16 +9,6 @@ import ( "github.com/rs/zerolog/log" ) -var bot *linebot.Client - -func setupLine() { - var err error - bot, err = linebot.New(LINE_SECRET, LINE_TOKEN) - if err != nil { - panic(err) - } -} - func webhook(c *gin.Context) { events, err := bot.ParseRequest(c.Request) if err != nil { @@ -43,7 +33,15 @@ func webhook(c *gin.Context) { } func controller(event *linebot.Event) { - switch event.Source.Ty { + + msg, ok := event.Message.(*linebot.TextMessage) + if !ok { + log.Error().Msg("controller not impemented") + return + } + Hit(msg.Text, event.Source.UserID) + + switch msg.Text { case "": default: diff --git a/api_user.go b/api_user.go new file mode 100644 index 0000000..996077b --- /dev/null +++ b/api_user.go @@ -0,0 +1,73 @@ +package main + +import ( + "path/filepath" + "strconv" + "strings" + "time" + + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "github.com/rs/zerolog/log" +) + +func ApiUpdateEmail(c *gin.Context) { + data := struct { + ID string `json:"id"` + Email string `json:"email"` + }{} + if err := c.ShouldBindJSON(&data); err != nil { + panic(err) + } + usr := &User{} + if err := DB.First(usr, "id = ?", data.ID).Error; err != nil { + // create user fallback + log.Error().Err(err).Msg("No User") + } + DB.Model(&User{}).Where("id = ?", data.ID).Update("email", data.Email) + OK(c, "ok") +} + +func ApiPostReceipt(c *gin.Context) { + oid := c.Param("oid") + if oid == "" { + panic(ErrorBadRequest) + } + + // order exists + order := &Order{} + if err := DB.First(order, "id = ?", oid).Error; err != nil { + panic(err) + } + + // get file + f, err := c.FormFile("file") + if err != nil { + panic(err) + } + id := uuid.New() + ext := filepath.Ext(f.Filename) + storedFileName := strings.Replace(id.String(), "-", "", -1) + ext + t := time.Now() + dir := filepath.Join( + strconv.Itoa(t.Year()), + strconv.Itoa(int(t.Month())), + ) + dest := filepath.Join( + "attachment", + dir, + ) + Mkdir(dest) + + // save file + dest = filepath.Join(dest, storedFileName) + if err = c.SaveUploadedFile(f, dest); err != nil { + panic(err) + } + if err = DB.Model(order).Update("attachment", filepath.Join(dir, storedFileName)). + Error; err != nil { + panic(err) + } + + OK(c, "ok") +} diff --git a/deploy.sh b/deploy.sh index 414a59a..60ddb8f 100644 --- a/deploy.sh +++ b/deploy.sh @@ -26,7 +26,7 @@ for PLATFORM in $PLATFORMS; do scp ${DIST}/${BIN_FILENAME} root@bot.ework.tw:~ ssh root@bot.ework.tw chmod +x talent ssh root@bot.ework.tw screen -X quit - ssh root@bot.ework.tw screen -d -m bash -c './talent -dev -db-name talentdev | tee talent.log' + ssh root@bot.ework.tw screen -d -m ./talent -dev done if [[ "${FAILURES}" != "" ]]; then diff --git a/go.mod b/go.mod index 9964772..6a7b35d 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.17 require ( github.com/fatih/color v1.13.0 github.com/gin-gonic/gin v1.7.7 + github.com/google/uuid v1.3.0 github.com/line/line-bot-sdk-go/v7 v7.11.0 github.com/rs/xid v1.3.0 github.com/rs/zerolog v1.26.1 diff --git a/go.sum b/go.sum index ef46ff0..9e56b27 100644 --- a/go.sum +++ b/go.sum @@ -48,6 +48,8 @@ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= diff --git a/main.go b/main.go index 8bfc27f..8730c08 100644 --- a/main.go +++ b/main.go @@ -54,6 +54,11 @@ func main() { // setup route server.GET("/", func(c *gin.Context) { OK(c, "ok") }) + // setup api + api := server.Group("api") + api.POST("/email", ApiUpdateEmail) + api.POST("/attach/:oid", ApiPostReceipt) + // setup bot webhook hook := server.Group("bot") hook.POST("/", webhook) diff --git a/model.go b/model.go index 953c98c..882b3ff 100644 --- a/model.go +++ b/model.go @@ -4,6 +4,7 @@ import ( "time" "github.com/rs/xid" + "github.com/rs/zerolog/log" "gorm.io/gorm" ) @@ -35,7 +36,7 @@ type Profile struct { type Product struct { ID uint `gorm:"primaryKey"` - Type string + Categories []Category `gorm:"many2many:product_categories;"` Name string Brief string Description string @@ -44,10 +45,20 @@ type Product struct { UpdatedAt time.Time } +type Category struct { + Name string `gorm:"primaryKey"` +} + type Order struct { + ID string + UserID string `gorm:"primaryKey"` ProductID uint `gorm:"primaryKey"` + Start time.Time + End time.Time + Attachment string + Price float32 CreatedAt time.Time @@ -61,7 +72,6 @@ type Node struct { UserID string CreatedAt time.Time - UpdatedAt time.Time } // BeforeCreate set UID @@ -72,3 +82,22 @@ func (u *User) BeforeCreate(tx *gorm.DB) (err error) { u.LastLogin = time.Now() return } + +func (u *User) AfterFind(tx *gorm.DB) (err error) { + if u.ProfileID != 0 { + profile := &Profile{} + if err := tx.First(profile, "id = ?", u.ProfileID).Error; err != nil { + log.Error().Err(err).Msg("get profile error") + } else { + u.Profile = *profile + } + } + return +} + +func (o *Order) BeforeCreate(tx *gorm.DB) (err error) { + if o.ID == "" { + o.ID = xid.New().String() + } + return +} diff --git a/run.sh b/run.sh new file mode 100644 index 0000000..f9a200f --- /dev/null +++ b/run.sh @@ -0,0 +1 @@ +go run *.go -dev -db-name talentdev -addr 127.0.0.1:8000 \ No newline at end of file diff --git a/setup_log.go b/setup.go similarity index 85% rename from setup_log.go rename to setup.go index 7f54127..91b2fed 100644 --- a/setup_log.go +++ b/setup.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/fatih/color" + "github.com/line/line-bot-sdk-go/v7/linebot" "github.com/rs/zerolog" "github.com/rs/zerolog/log" ) @@ -52,10 +53,12 @@ func setupLog() { zerolog.DurationFieldInteger = true } -func Hit(name, uid string) { - n := &Node{ - Name: name, - UserID: uid, +var bot *linebot.Client + +func setupLine() { + var err error + bot, err = linebot.New(LINE_SECRET, LINE_TOKEN) + if err != nil { + panic(err) } - DB.Create(n) } diff --git a/test_data.go b/test_data.go new file mode 100644 index 0000000..06ab7d0 --- /dev/null +++ b/test_data.go @@ -0,0 +1 @@ +package main diff --git a/util.go b/util.go new file mode 100644 index 0000000..46aae80 --- /dev/null +++ b/util.go @@ -0,0 +1,48 @@ +package main + +import ( + "os" + "path/filepath" + + "github.com/line/line-bot-sdk-go/v7/linebot" + "github.com/rs/zerolog/log" +) + +func Mkdir(args ...interface{}) error { + var path string + var mode os.FileMode + mode = 0755 + for _, arg := range args { + switch arg := arg.(type) { + case string: + path = filepath.Join(path, arg) + case os.FileMode: + mode = arg + } + } + return os.MkdirAll(path, mode) +} + +func Hit(name, uid string) { + n := &Node{ + Name: name, + UserID: uid, + } + go DB.Create(n) +} + +func SendMessage(replyToken string, to string, messages ...linebot.SendingMessage) (*linebot.BasicResponse, error) { + if replyToken != "" { + res, err := bot.ReplyMessage(replyToken, messages...).Do() + if err != nil { + log.Error().Err(err).Caller().Interface("response", res).Msg("reply error") + } + return res, err + } else { + res, err := bot.PushMessage(to, messages...).Do() + if err != nil { + log.Error().Err(err).Caller().Interface("response", res).Msg("push error") + } + return res, err + } +}