Commit f68f5df4 by chenxianqi

Optimize the code

parent c6b2c7ad
Showing with 1739 additions and 996 deletions
......@@ -23,9 +23,9 @@ mimc_HttpUrl = "https://mimc.chat.xiaomi.net/api/account/token"
[dev]
httpaddr = "localhost"
# 小米mimc配置信息(小米开放平台创建)
mimc_appId =
mimc_appKey = ""
mimc_appSecret = ""
mimc_appId = 2882303761517669588
mimc_appKey = "5111766983588"
mimc_appSecret = "b0L3IOz/9Ob809v8H2FbVg=="
# IM数据库信息
im_alias_name = "default"
im_driver_name= "mysql"
......
package configs
// Some global static configuration information can be put here
// ResponseStatusType enum type
type ResponseStatusType int
// const Response status
const (
ResponseError ResponseStatusType = 500
ResponseSucess ResponseStatusType = 200
ResponseFail ResponseStatusType = 401
ResponseNotFound ResponseStatusType = 404
)
package controllers
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"kefu_server/models"
"kefu_server/utils"
"time"
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
"github.com/astaxie/beego/validation"
)
// AuthController struct
type AuthController struct {
beego.Controller
}
// LoginRequest login
// auth_type 登录客户端标识ID
// username 用户名
// password 密码
type LoginRequest struct {
AuthType int64 `json:"auth_type"`
UserName string `json:"username"`
Password string `ojson:"password"`
}
// Login admin login
func (c *AuthController) Login() {
var loginRequest LoginRequest
valid := validation.Validation{}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &loginRequest); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "参数错误", nil)
c.ServeJSON()
return
}
// valid
valid.Required(loginRequest.UserName, "username").Message("用户名不能为空!")
valid.Required(loginRequest.Password, "password").Message("密码不能为空!")
valid.Required(loginRequest.AuthType, "auth_type").Message("登录客户端标识auth_type不能为空!")
if valid.HasErrors() {
for _, err := range valid.Errors {
c.Data["json"] = utils.ResponseError(c.Ctx, err.Message, nil)
break
}
c.ServeJSON()
return
}
// MD5
m5 := md5.New()
m5.Write([]byte(loginRequest.Password))
loginRequest.Password = hex.EncodeToString(m5.Sum(nil))
o := orm.NewOrm()
/// auth_type exist ?
authType := models.AuthTypes{ID: loginRequest.AuthType}
if err := o.Read(&authType); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "客户端标识不存在!", nil)
c.ServeJSON()
return
}
queryAdmin := models.Admin{UserName: loginRequest.UserName}
err := o.Read(&queryAdmin, "UserName")
if err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "用户不存在!", nil)
} else if queryAdmin.Password != loginRequest.Password {
c.Data["json"] = utils.ResponseError(c.Ctx, "密码错误!", nil)
} else if loginRequest.UserName != queryAdmin.UserName {
c.Data["json"] = utils.ResponseError(c.Ctx, "用户不存在!", nil)
} else {
newToken := utils.GenerateToken(models.JwtKey{ID: queryAdmin.ID, UserName: queryAdmin.UserName, AuthType: authType.ID})
auth := models.Auths{}
as := o.QueryTable(auth)
if err := as.Filter("auth_type", loginRequest.AuthType).Filter("uid", queryAdmin.ID).One(&auth); err != nil {
auth.Token = newToken
auth.UID = queryAdmin.ID
auth.AuthType = authType.ID
auth.UpdateAt = time.Now().Unix()
auth.CreateAt = time.Now().Unix()
if _, err := o.Insert(&auth); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "登录失败", &err)
c.ServeJSON()
return
}
} else {
auth.Token = newToken
auth.UpdateAt = time.Now().Unix()
o.Update(&auth)
}
queryAdmin.Password = ""
queryAdmin.Token = newToken
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "登录成功!", queryAdmin)
}
c.ServeJSON()
}
// Logout admin logout
func (c *AuthController) Logout() {
o := orm.NewOrm()
token := c.Ctx.Input.Header("Authorization")
_auth := models.Auths{Token: token}
if err := o.Read(&_auth, "Token"); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "登录已失效!", nil)
c.ServeJSON()
return
}
qs := o.QueryTable(models.Auths{})
if count, _ := qs.Filter("uid", _auth.UID).Count(); count <= 1 {
admin := models.Admin{ID: _auth.UID}
_ = o.Read(&admin)
admin.CurrentConUser = 0
admin.Online = 0
if _, err := o.Update(&admin); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "退出失败!", nil)
c.ServeJSON()
return
}
}
o.Delete(&_auth)
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "退出成功!", nil)
c.ServeJSON()
}
package controllers
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"kefu_server/configs"
"kefu_server/models"
"kefu_server/services"
"kefu_server/utils"
"time"
"github.com/astaxie/beego/orm"
"github.com/astaxie/beego/validation"
)
// AuthController struct
type AuthController struct {
BaseController
AuthTypesRepository *services.AuthTypesRepository
AdminRepository *services.AdminRepository
AuthsRepository *services.AuthsRepository
}
// Prepare More like construction method
func (c *AuthController) Prepare() {
// init AuthTypes
c.AuthTypesRepository = new(services.AuthTypesRepository)
c.AuthTypesRepository.Init(new(models.AuthTypes))
// init AdminRepository
c.AdminRepository = new(services.AdminRepository)
c.AdminRepository.Init(new(models.Admin))
// init AuthsRepository
c.AuthsRepository = new(services.AuthsRepository)
c.AuthsRepository.Init(new(models.Auths))
}
// Finish Comparison like destructor
func (c *AuthController) Finish() {}
// LoginRequest login
// auth_type 登录客户端标识ID
// username 用户名
// password 密码
type LoginRequest struct {
AuthType int64 `json:"auth_type"`
UserName string `json:"username"`
Password string `ojson:"password"`
}
// Login admin login
func (c *AuthController) Login() {
var request LoginRequest
valid := validation.Validation{}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &request); err != nil {
c.JSON(configs.ResponseFail, "参数错误", nil)
}
// valid
valid.Required(request.UserName, "username").Message("用户名不能为空!")
valid.Required(request.Password, "password").Message("密码不能为空!")
valid.Required(request.AuthType, "auth_type").Message("登录客户端标识auth_type不能为空!")
if valid.HasErrors() {
for _, err := range valid.Errors {
c.JSON(configs.ResponseFail, err.Message, nil)
}
}
// MD5
m5 := md5.New()
m5.Write([]byte(request.Password))
request.Password = hex.EncodeToString(m5.Sum(nil))
/// auth_type exist ?
authType := c.AuthTypesRepository.GetAuthType(request.AuthType)
if authType == nil {
c.JSON(configs.ResponseFail, "客户端标识不存在!", nil)
}
queryAdmin := c.AdminRepository.GetAdminWithUserName(request.UserName)
if queryAdmin == nil {
c.JSON(configs.ResponseFail, "用户不存在!", nil)
}
if queryAdmin.Password != request.Password {
c.JSON(configs.ResponseFail, "密码错误!", nil)
}
if request.UserName != queryAdmin.UserName {
c.JSON(configs.ResponseFail, "用户不存在!", nil)
}
// create token
newToken := utils.GenerateToken(models.JwtKey{ID: queryAdmin.ID, UserName: queryAdmin.UserName, AuthType: authType.ID})
auth := c.AuthsRepository.GetAuthInfoWithTypeAndUID(request.AuthType, queryAdmin.ID)
if auth == nil {
newAuth := models.Auths{
Token: newToken,
UID: queryAdmin.ID,
AuthType: authType.ID,
UpdateAt: time.Now().Unix(),
CreateAt: time.Now().Unix(),
}
if _, err := c.AuthsRepository.Add(&newAuth); err != nil {
c.JSON(configs.ResponseFail, "登录失败!", nil)
}
} else {
_, err := c.AuthsRepository.UpdateParams(auth.ID, orm.Params{
"Token": newToken,
"UpdateAt": time.Now().Unix(),
})
if err != nil {
c.JSON(configs.ResponseFail, "登录失败!", nil)
}
}
queryAdmin.Password = "*****"
queryAdmin.Token = newToken
c.JSON(configs.ResponseSucess, "登录成功!!", &queryAdmin)
}
// Logout admin logout
func (c *AuthController) Logout() {
// GetAuthInfo
auth := c.GetAuthInfo()
if count := c.AuthsRepository.GetAdminOnlineCount(auth.UID); count <= 1 {
if _, err := c.AdminRepository.UpdateParams(auth.UID, orm.Params{
"CurrentConUser": 0,
"Online": 0,
}); err != nil {
c.JSON(configs.ResponseFail, "退出失败!", &err)
}
}
if row, err := c.AuthsRepository.Delete(auth.ID); err != nil || row == 0 {
c.JSON(configs.ResponseFail, "退出失败!", &err)
}
c.JSON(configs.ResponseSucess, "退出成功!", nil)
}
package controllers
import (
"kefu_server/configs"
"kefu_server/models"
"kefu_server/services"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
)
// BaseControllerInterface interface
type BaseControllerInterface interface {
JSON()
Prepare()
GetAuthInfo() *models.Auths
}
// BaseController Base class
type BaseController struct {
beego.Controller
}
// JSON handle http Response
// Return json data, and stop moving on
func (c *BaseController) JSON(status configs.ResponseStatusType, message string, data interface{}) {
c.Ctx.Output.Header("Access-Control-Max-Age", "2592000")
msg := message
if status != configs.ResponseSucess && status != configs.ResponseFail {
msg = "sorry server error"
data = nil
}
c.Data["json"] = &models.Response{Code: status, Message: msg, Data: &data}
c.ServeJSON()
c.StopRun()
}
// GetAuthInfo get current anth user that AuthInfo
func (c *BaseController) GetAuthInfo() *models.Auths {
token := c.Ctx.Input.Header("Authorization")
var authsRepository = new(services.AuthsRepository)
authsRepository.Init(new(models.Auths))
auth := authsRepository.GetAuthInfo(token)
if auth == nil {
logs.Warn("GetAuthInfo fun error------------登录已失效!")
c.JSON(configs.ResponseFail, "登录已失效!", nil)
}
return auth
}
......@@ -2,32 +2,40 @@ package controllers
import (
"encoding/json"
"kefu_server/configs"
"kefu_server/models"
"kefu_server/utils"
"kefu_server/services"
"time"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
"github.com/astaxie/beego/validation"
)
// CompanyController struct
type CompanyController struct {
beego.Controller
BaseController
CompanyRepository *services.CompanyRepository
}
// Prepare More like construction method
func (c *CompanyController) Prepare() {
// init CompanyRepository
c.CompanyRepository = new(services.CompanyRepository)
c.CompanyRepository.Init(new(models.Company))
}
// Finish Comparison like destructor
func (c *CompanyController) Finish() {}
// Get get conpany info
func (c *CompanyController) Get() {
o := orm.NewOrm()
company := models.Company{ID: 1}
if err := o.Read(&company); err != nil {
logs.Error(err)
c.Data["json"] = utils.ResponseError(c.Ctx, "查询失败!", err)
} else {
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "查询成功!", &company)
company := c.CompanyRepository.GetCompany(1)
if company == nil {
c.JSON(configs.ResponseFail, "查询失败!", nil)
}
c.ServeJSON()
c.JSON(configs.ResponseSucess, "查询成功!", &company)
}
// Put update conpany info
......@@ -36,10 +44,7 @@ func (c *CompanyController) Put() {
company := models.Company{}
company.UpdateAt = time.Now().Unix()
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &company); err != nil {
logs.Error(err)
c.Data["json"] = utils.ResponseError(c.Ctx, "参数错误!", nil)
c.ServeJSON()
return
c.JSON(configs.ResponseFail, "参数错误!", nil)
}
// validation
......@@ -53,23 +58,22 @@ func (c *CompanyController) Put() {
valid.MaxSize(company.Tel, 50, "tel").Message("公司电话长度不能超过50个字符!")
if valid.HasErrors() {
for _, err := range valid.Errors {
logs.Error(err)
c.Data["json"] = &models.Response{Code: 400, Message: err.Message, Data: nil}
break
c.JSON(configs.ResponseFail, err.Message, nil)
}
c.ServeJSON()
return
}
// orm
o := orm.NewOrm()
company.ID = 1
company.UpdateAt = time.Now().Unix()
if _, err := o.Update(&company); err != nil {
logs.Error(err)
c.Data["json"] = utils.ResponseError(c.Ctx, "更新失败!", err)
} else {
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "更新成功!", &company)
row, err := c.CompanyRepository.UpdateParams(1, orm.Params{
"Title": company.Title,
"Address": company.Address,
"Email": company.Email,
"UpdateAt": time.Now().Unix(),
"Logo": company.Logo,
"Service": company.Service,
"Tel": company.Tel,
})
if err != nil {
c.JSON(configs.ResponseFail, "更新失败!", nil)
}
c.ServeJSON()
c.JSON(configs.ResponseSucess, "更新成功!", row)
}
package controllers
import (
"encoding/base64"
"kefu_server/models"
"kefu_server/utils"
"strconv"
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
)
// ContactController struct
type ContactController struct {
beego.Controller
}
// GetContacts get all Contacts
func (c *ContactController) GetContacts() {
o := orm.NewOrm()
token := c.Ctx.Input.Header("Authorization")
_auth := models.Auths{Token: token}
if err := o.Read(&_auth, "Token"); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "登录已失效!", nil)
c.ServeJSON()
return
}
admin := models.Admin{ID: _auth.UID}
_ = o.Read(&admin)
var contactData []models.ContactData
rCount, err := o.Raw("SELECT c.id AS cid,c.to_account,c.is_session_end, c.last_message,c.last_message_type,c.from_account, c.create_at AS contact_create_at,u.*, IFNULL(m.`count`,0) AS `read` FROM `contact` c LEFT JOIN `user` u ON c.from_account = u.id LEFT JOIN (SELECT to_account,from_account, COUNT(*) as `count` FROM message WHERE `read` = 1 GROUP BY to_account,from_account) m ON m.to_account = c.to_account AND m.from_account = c.from_account WHERE c.to_account = ? AND c.delete = 0 ORDER BY c.create_at DESC", admin.ID).QueryRows(&contactData)
if err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "查询失败!", err)
} else {
if rCount == 0 {
contactData = []models.ContactData{}
}
// base 64
for index, contact := range contactData {
payload, _ := base64.StdEncoding.DecodeString(contact.LastMessage)
contactData[index].LastMessage = string(payload)
}
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "查询成功!", &contactData)
}
c.ServeJSON()
}
// Delete a Contact
func (c *ContactController) Delete() {
o := orm.NewOrm()
id, _ := strconv.ParseInt(c.Ctx.Input.Param(":id"), 10, 64)
token := c.Ctx.Input.Header("Authorization")
_auth := models.Auths{Token: token}
if err := o.Read(&_auth, "Token"); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "登录已失效!", nil)
c.ServeJSON()
return
}
admin := models.Admin{ID: _auth.UID}
_ = o.Read(&admin)
res, _ := o.Raw("UPDATE `contact` SET `delete` = 1 WHERE id = ? AND to_account = ?", id, admin.ID).Exec()
if rowsAffected, _ := res.RowsAffected(); rowsAffected == 0 {
c.Data["json"] = utils.ResponseError(c.Ctx, "删除失败!", nil)
} else {
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "删除成功!", nil)
}
c.ServeJSON()
}
// Clear all
func (c *ContactController) Clear() {
o := orm.NewOrm()
token := c.Ctx.Input.Header("Authorization")
_auth := models.Auths{Token: token}
if err := o.Read(&_auth, "Token"); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "登录已失效!", nil)
c.ServeJSON()
return
}
admin := models.Admin{ID: _auth.UID}
_ = o.Read(&admin)
res, _ := o.Raw("UPDATE `contact` SET `delete` = 1 WHERE to_account = ?", admin.ID).Exec()
if rowsAffected, _ := res.RowsAffected(); rowsAffected == 0 {
c.Data["json"] = utils.ResponseError(c.Ctx, "清空失败!", nil)
} else {
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "清空成功!", nil)
}
c.ServeJSON()
}
package controllers
import (
"kefu_server/configs"
"kefu_server/models"
"kefu_server/services"
"strconv"
)
// ContactController struct
type ContactController struct {
BaseController
ContactRepository *services.ContactRepository
AdminRepository *services.AdminRepository
}
// Prepare More like construction method
func (c *ContactController) Prepare() {
// init ContactRepository
c.ContactRepository = new(services.ContactRepository)
c.ContactRepository.Init(new(models.Contact))
// init AdminRepository
c.AdminRepository = new(services.AdminRepository)
c.AdminRepository.Init(new(models.Admin))
}
// Finish Comparison like destructor
func (c *ContactController) Finish() {}
// GetContacts get all Contacts
func (c *ContactController) GetContacts() {
// GetAuthInfo
auth := c.GetAuthInfo()
contactData, err := c.ContactRepository.GetContacts(auth.UID)
if err != nil {
c.JSON(configs.ResponseFail, "查询失败!", &err)
}
if len(contactData) == 0 {
contactData = []models.ContactData{}
}
c.JSON(configs.ResponseSucess, "查询成功!", &contactData)
}
// Delete a Contact
func (c *ContactController) Delete() {
id, _ := strconv.ParseInt(c.Ctx.Input.Param(":id"), 10, 64)
// GetAuthInfo
auth := c.GetAuthInfo()
// delete
rows, err := c.ContactRepository.Delete(id, auth.UID)
if err != nil || rows == 0 {
c.JSON(configs.ResponseFail, "删除失败!", &err)
}
c.JSON(configs.ResponseSucess, "删除成功!", rows)
}
// DeleteAll all
func (c *ContactController) DeleteAll() {
// GetAuthInfo
auth := c.GetAuthInfo()
// delete
rows, err := c.ContactRepository.DeleteAll(auth.UID)
if err != nil {
c.JSON(configs.ResponseFail, "清空成功!", &err)
}
c.JSON(configs.ResponseSucess, "清空成功!", rows)
}
package controllers
import (
"github.com/astaxie/beego"
)
import "kefu_server/configs"
// ErrorController struct
type ErrorController struct {
beego.Controller
BaseController
}
// Error404 Controller public fun
func (c *ErrorController) Error404() {
c.Data["content"] = "page not found"
c.TplName = "404.tpl"
c.JSON(configs.ResponseNotFound, "Sorry The Page Not Found~", nil)
}
package controllers
import (
"encoding/json"
"kefu_server/models"
"kefu_server/utils"
"math"
"time"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
"github.com/astaxie/beego/validation"
)
// HomeController struct
type HomeController struct {
beego.Controller
}
// StatisticalRequest home Statistical
type StatisticalRequest struct {
DateStart string `json:"date_start"`
DateEnd string `json:"date_end"`
}
// Statistical statistical services
func (c *HomeController) Statistical() {
o := orm.NewOrm()
token := c.Ctx.Input.Header("Authorization")
_auth := models.Auths{Token: token}
if err := o.Read(&_auth, "Token"); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "登录已失效!", nil)
c.ServeJSON()
return
}
admin := models.Admin{ID: _auth.UID}
if err := o.Read(&admin); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "查询失败,用户不存在", err)
c.ServeJSON()
return
}
// request body
statisticalRequest := StatisticalRequest{}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &statisticalRequest); err != nil {
logs.Error(err)
c.Data["json"] = utils.ResponseError(c.Ctx, "参数错误!", nil)
c.ServeJSON()
return
}
// validation
valid := validation.Validation{}
valid.Required(statisticalRequest.DateStart, "date_start").Message("date_start不能为空!")
valid.Required(statisticalRequest.DateEnd, "date_end").Message("date_end不能为空!")
if valid.HasErrors() {
for _, err := range valid.Errors {
c.Data["json"] = utils.ResponseError(c.Ctx, err.Message, nil)
break
}
c.ServeJSON()
return
}
// transform date
var oneDaySecond float64 = 86400
layoutDate := "2006-01-02 15:04:05"
loc, _ := time.LoadLocation("Local")
dateStartString := statisticalRequest.DateStart + " 00:00:00"
dateEndString := statisticalRequest.DateEnd + " 23:59:59"
dateStart, _ := time.ParseInLocation(layoutDate, dateStartString, loc)
dateEnd, _ := time.ParseInLocation(layoutDate, dateEndString, loc)
k := dateEnd.Unix() - dateStart.Unix()
maxDay := int(math.Ceil(float64(k) / oneDaySecond))
if maxDay < 1 || maxDay >= 32 {
c.Data["json"] = utils.ResponseError(c.Ctx, "日期有误,最大只能查询一个月以内", nil)
c.ServeJSON()
return
}
countsArr := map[string]interface{}{}
// Count customer service access
var membersData []orm.Params
_, _ = o.Raw("SELECT a.id, a.username, a.nickname, IFNULL(s.count,0) as count FROM `admin` a LEFT JOIN (SELECT service_account,COUNT(*) AS count FROM services_statistical WHERE `create_at` BETWEEN ? AND ? GROUP BY service_account) s ON a.id = s.service_account ORDER BY a.id", dateStart.Unix(), dateEnd.Unix()).Values(&membersData)
countsArr["members"] = membersData
// Count the traffic of each channel
var statisticalData []interface{}
for i := 0; i < maxDay; i++ {
var statisticalTemp []orm.Params
increment := int64(i) * int64(oneDaySecond)
start := dateStart.Unix() + increment
end := start + int64(oneDaySecond)
if i == maxDay-1 {
end = dateEnd.Unix()
}
_, _ = o.Raw("SELECT p.id, p.title, IFNULL(s.count,0) as count FROM `platform` p LEFT JOIN (SELECT platform,COUNT(*) AS count FROM `services_statistical` WHERE `create_at` BETWEEN ? AND ? GROUP BY platform) s ON p.id = s.platform ORDER BY p.id", start, end).Values(&statisticalTemp)
day := time.Unix(start, 0).Format("2006-01-02")
statisticalArrItem := map[string]interface{}{}
statisticalArrItem["date"] = day
statisticalArrItem["list"] = statisticalTemp
statisticalData = append(statisticalData, statisticalArrItem)
}
countsArr["statistical"] = statisticalData
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "查询成功!", &countsArr)
c.ServeJSON()
}
// TodayActionStatistical today Statistical
func (c *HomeController) TodayActionStatistical() {
o := orm.NewOrm()
token := c.Ctx.Input.Header("Authorization")
_auth := models.Auths{Token: token}
if err := o.Read(&_auth, "Token"); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "登录已失效!", nil)
c.ServeJSON()
return
}
admin := models.Admin{ID: _auth.UID}
if err := o.Read(&admin); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "查询失败,用户不存在", err)
c.ServeJSON()
return
}
// request body
statisticalRequest := StatisticalRequest{}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &statisticalRequest); err != nil {
logs.Error(err)
c.Data["json"] = utils.ResponseError(c.Ctx, "参数错误!", nil)
c.ServeJSON()
return
}
// validation
valid := validation.Validation{}
valid.Required(statisticalRequest.DateStart, "date_start").Message("date_start不能为空!")
valid.Required(statisticalRequest.DateEnd, "date_end").Message("date_end不能为空!")
if valid.HasErrors() {
for _, err := range valid.Errors {
c.Data["json"] = utils.ResponseError(c.Ctx, err.Message, nil)
break
}
c.ServeJSON()
return
}
// transform date
layoutDate := "2006-01-02 15:04:05"
loc, _ := time.LoadLocation("Local")
dateStartString := statisticalRequest.DateStart + " 00:00:00"
dateEndString := statisticalRequest.DateEnd + " 23:59:59"
dateStart, _ := time.ParseInLocation(layoutDate, dateStartString, loc)
dateEnd, _ := time.ParseInLocation(layoutDate, dateEndString, loc)
var statisticalData []orm.Params
_, _ = o.Raw("SELECT p.id platform,p.title, IFNULL(u.count,0) AS `count` FROM platform as p LEFT JOIN (SELECT platform,COUNT(*) AS count FROM `user` WHERE last_activity BETWEEN ? AND ? GROUP BY platform) u ON p.id = u.platform", dateStart.Unix(), dateEnd.Unix()).Values(&statisticalData)
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "查询成功!", &statisticalData)
c.ServeJSON()
}
package controllers
import (
"encoding/json"
"kefu_server/configs"
"kefu_server/models"
"kefu_server/services"
"github.com/astaxie/beego/validation"
)
// HomeController struct
type HomeController struct {
BaseController
StatisticalRepository *services.StatisticalRepository
}
// Prepare More like construction method
func (c *HomeController) Prepare() {
// init StatisticalRepository
c.StatisticalRepository = new(services.StatisticalRepository)
c.StatisticalRepository.Init(new(models.ServicesStatistical))
}
// Finish Comparison like destructor
func (c *HomeController) Finish() {}
// StatisticalRequest home Statistical
type StatisticalRequest struct {
DateStart string `json:"date_start"`
DateEnd string `json:"date_end"`
}
// Statistical statistical services
func (c *HomeController) Statistical() {
// request body
statisticalRequest := StatisticalRequest{}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &statisticalRequest); err != nil {
c.JSON(configs.ResponseFail, "参数错误!", &err)
}
// validation
valid := validation.Validation{}
valid.Required(statisticalRequest.DateStart, "date_start").Message("date_start不能为空!")
valid.Required(statisticalRequest.DateEnd, "date_end").Message("date_end不能为空!")
if valid.HasErrors() {
for _, err := range valid.Errors {
c.JSON(configs.ResponseFail, err.Message, &err)
}
}
countsArr, err := c.StatisticalRepository.GetStatisticals(statisticalRequest.DateStart, statisticalRequest.DateEnd)
if err != nil {
c.JSON(configs.ResponseFail, err.Error(), &err)
}
c.JSON(configs.ResponseSucess, "查询成功!", &countsArr)
}
// TodayActionStatistical today Statistical
func (c *HomeController) TodayActionStatistical() {
// request body
statisticalRequest := StatisticalRequest{}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &statisticalRequest); err != nil {
c.JSON(configs.ResponseFail, "参数错误!", &err)
}
// validation
valid := validation.Validation{}
valid.Required(statisticalRequest.DateStart, "date_start").Message("date_start不能为空!")
valid.Required(statisticalRequest.DateEnd, "date_end").Message("date_end不能为空!")
if valid.HasErrors() {
for _, err := range valid.Errors {
c.JSON(configs.ResponseFail, err.Message, &err)
}
}
statisticalData, err := c.StatisticalRepository.GetTodayActionStatistical(statisticalRequest.DateStart, statisticalRequest.DateEnd)
if err != nil {
c.JSON(configs.ResponseFail, err.Error(), &err)
}
c.JSON(configs.ResponseSucess, "查询成功!", &statisticalData)
}
package controllers
import (
"encoding/json"
"kefu_server/models"
"kefu_server/utils"
"strconv"
"strings"
"time"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
"github.com/astaxie/beego/validation"
)
// KnowledgeBaseController struct
type KnowledgeBaseController struct {
beego.Controller
}
// Get get a knowledge Base
func (c *KnowledgeBaseController) Get() {
o := orm.NewOrm()
id, _ := strconv.ParseInt(c.Ctx.Input.Param(":id"), 10, 64)
knowledgeBase := models.KnowledgeBase{ID: id}
if err := o.Read(&knowledgeBase); err != nil {
logs.Error(err)
c.Data["json"] = utils.ResponseError(c.Ctx, "获取失败!", err)
c.ServeJSON()
}
knowledgeBase.SubTitle = strings.Trim(knowledgeBase.SubTitle, "|")
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "查询成功!", &knowledgeBase)
c.ServeJSON()
}
// Post add a knowledge Base
func (c *KnowledgeBaseController) Post() {
o := orm.NewOrm()
// request body
var knowledgeBase models.KnowledgeBase
knowledgeBase.CreateAt = time.Now().Unix()
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &knowledgeBase); err != nil {
logs.Error(err)
c.Data["json"] = utils.ResponseError(c.Ctx, "参数错误!", err)
c.ServeJSON()
}
// exist title ?
oldKnowledgeBase := models.KnowledgeBase{Title: knowledgeBase.Title}
if err := o.Read(&oldKnowledgeBase, "Title"); err == nil {
logs.Error(err)
c.Data["json"] = utils.ResponseError(c.Ctx, "标题已存在,请换个标题!", nil)
c.ServeJSON()
return
}
// validation
valid := validation.Validation{}
valid.Required(knowledgeBase.Title, "title").Message("标题不能为空!")
valid.Required(knowledgeBase.Content, "content").Message("内容不能为空!")
valid.Required(knowledgeBase.UID, "uid").Message("用户ID不能为空!")
if valid.HasErrors() {
for _, err := range valid.Errors {
logs.Error(err)
c.Data["json"] = utils.ResponseError(c.Ctx, err.Message, nil)
break
}
c.ServeJSON()
return
}
// Platform exist
if err := o.Read(&models.Platform{ID: knowledgeBase.Platform}); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "不存在的平台id!", nil)
c.ServeJSON()
return
}
// insert
knowledgeBase.SubTitle = strings.Trim(knowledgeBase.SubTitle, "|")
if knowledgeBase.SubTitle != "" {
knowledgeBase.SubTitle = "|" + knowledgeBase.SubTitle + "|"
}
if id, err := o.Insert(&knowledgeBase); err == nil {
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "添加成功!", &id)
} else {
logs.Error(err)
c.Data["json"] = utils.ResponseError(c.Ctx, "服务异常!", err)
}
c.ServeJSON()
}
// Put update a knowledge Base
func (c *KnowledgeBaseController) Put() {
o := orm.NewOrm()
// request body
var newKnowledgeBase models.KnowledgeBase
newKnowledgeBase.UpdateAt = time.Now().Unix()
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &newKnowledgeBase); err != nil {
logs.Error(err)
c.Data["json"] = utils.ResponseError(c.Ctx, "参数错误!", err)
c.ServeJSON()
}
// validation
valid := validation.Validation{}
valid.Required(newKnowledgeBase.Title, "title").Message("标题不能为空!")
valid.Required(newKnowledgeBase.Content, "content").Message("内容不能为空!")
valid.Required(newKnowledgeBase.UID, "uid").Message("用户ID不能为空!")
if valid.HasErrors() {
for _, err := range valid.Errors {
c.Data["json"] = utils.ResponseError(c.Ctx, err.Message, nil)
break
}
c.ServeJSON()
return
}
// is exist ?
oldKnowledgeBase := models.KnowledgeBase{ID: newKnowledgeBase.ID}
if err := o.Read(&oldKnowledgeBase); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "内容不存在!", err)
c.ServeJSON()
}
// is exist title?
oldKnowledgeBase = models.KnowledgeBase{Title: newKnowledgeBase.Title}
if err := o.Read(&oldKnowledgeBase, "Title"); err == nil && oldKnowledgeBase.ID != newKnowledgeBase.ID {
c.Data["json"] = utils.ResponseError(c.Ctx, "标题已存在,请换个标题!", nil)
c.ServeJSON()
}
// is exist Platform?
if err := o.Read(&models.Platform{ID: newKnowledgeBase.Platform}); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "不存在的平台id!", nil)
c.ServeJSON()
return
}
// sub title
newKnowledgeBase.SubTitle = strings.Trim(newKnowledgeBase.SubTitle, "|")
if newKnowledgeBase.SubTitle != "" {
newKnowledgeBase.SubTitle = "|" + newKnowledgeBase.SubTitle + "|"
}
// insert
newKnowledgeBase.CreateAt = oldKnowledgeBase.CreateAt
if _, err := o.Update(&newKnowledgeBase, "Title", "SubTitle", "Content", "Platform", "UpdateAt"); err == nil {
newKnowledgeBase.SubTitle = strings.Trim(newKnowledgeBase.SubTitle, "|")
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "更新成功!", &newKnowledgeBase)
} else {
logs.Error(err)
c.Data["json"] = utils.ResponseError(c.Ctx, "更新失败!", err)
}
c.ServeJSON()
}
// Delete delete a knowledge Base
func (c *KnowledgeBaseController) Delete() {
o := orm.NewOrm()
id, _ := strconv.ParseInt(c.Ctx.Input.Param(":id"), 10, 64)
knowledgeBase := models.KnowledgeBase{ID: id}
// exist
if err := o.Read(&knowledgeBase); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "删除失败,内容不存在!", err)
c.ServeJSON()
return
}
if num, err := o.Delete(&knowledgeBase); err != nil {
logs.Error(err)
c.Data["json"] = utils.ResponseError(c.Ctx, "删除失败!", nil)
} else {
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "删除成功!", num)
}
c.ServeJSON()
}
// List quesy list
func (c *KnowledgeBaseController) List() {
// request body
var paginationData models.PaginationData
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &paginationData); err != nil {
logs.Error(err)
c.Data["json"] = utils.ResponseError(c.Ctx, "参数错误!", err)
c.ServeJSON()
return
}
// orm instance
o := orm.NewOrm()
model := new(models.KnowledgeBase)
qs := o.QueryTable(model)
// query
var lists []models.KnowledgeBase
if _, err := qs.OrderBy("-create_at").Limit(paginationData.PageSize).Offset((paginationData.PageOn - 1) * paginationData.PageSize).All(&lists); err != nil {
logs.Error(err)
c.Data["json"] = utils.ResponseError(c.Ctx, "查询失败!", err)
c.ServeJSON()
return
}
total, _ := qs.Count()
for index := range lists {
lists[index].SubTitle = strings.Trim(lists[index].SubTitle, "|")
}
paginationData.Total = total
paginationData.List = &lists
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "查询成功!", &paginationData)
c.ServeJSON()
}
package controllers
import (
"encoding/json"
"kefu_server/configs"
"kefu_server/models"
"kefu_server/services"
"strconv"
"strings"
"time"
"github.com/astaxie/beego/orm"
"github.com/astaxie/beego/validation"
)
// KnowledgeBaseController struct
type KnowledgeBaseController struct {
BaseController
PlatformRepository *services.PlatformRepository
KnowledgeBaseRepository *services.KnowledgeBaseRepository
}
// Prepare More like construction method
func (c *KnowledgeBaseController) Prepare() {
// init StatisticalRepository
c.KnowledgeBaseRepository = new(services.KnowledgeBaseRepository)
c.KnowledgeBaseRepository.Init(new(models.KnowledgeBase))
// init PlatformRepository
c.PlatformRepository = new(services.PlatformRepository)
c.PlatformRepository.Init(new(models.Platform))
}
// Finish Comparison like destructor
func (c *KnowledgeBaseController) Finish() {}
// Get get a knowledge Base
func (c *KnowledgeBaseController) Get() {
id, err := strconv.ParseInt(c.Ctx.Input.Param(":id"), 10, 64)
if err != nil {
c.JSON(configs.ResponseFail, "查询失败!", &err)
}
knowledgeBase := c.KnowledgeBaseRepository.GetKnowledgeBase(id)
if knowledgeBase == nil {
c.JSON(configs.ResponseFail, "查询失败!", nil)
}
c.JSON(configs.ResponseFail, "查询成功!", &knowledgeBase)
}
// Post add a knowledge Base
func (c *KnowledgeBaseController) Post() {
// request body
var knowledgeBase models.KnowledgeBase
knowledgeBase.CreateAt = time.Now().Unix()
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &knowledgeBase); err != nil {
c.JSON(configs.ResponseFail, "参数错误!", &err)
}
// validation
valid := validation.Validation{}
valid.Required(knowledgeBase.Title, "title").Message("标题不能为空!")
valid.Required(knowledgeBase.Content, "content").Message("内容不能为空!")
valid.Required(knowledgeBase.UID, "uid").Message("用户ID不能为空!")
if valid.HasErrors() {
for _, err := range valid.Errors {
c.JSON(configs.ResponseFail, err.Message, nil)
}
}
// Platform exist
if platform := c.PlatformRepository.GetPlatform(knowledgeBase.Platform); platform == nil {
c.JSON(configs.ResponseFail, "不存在的平台id!", nil)
}
// insert
isNewCreate, index, err := c.KnowledgeBaseRepository.Add(&knowledgeBase, "Title")
if !isNewCreate {
c.JSON(configs.ResponseFail, "标题已存在,请换个标题!", nil)
}
if err != nil {
c.JSON(configs.ResponseFail, "添加失败!", &err)
}
c.JSON(configs.ResponseSucess, "添加成功!", index)
}
// Put update a knowledge Base
func (c *KnowledgeBaseController) Put() {
// request body
var newKnowledgeBase models.KnowledgeBase
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &newKnowledgeBase); err != nil {
c.JSON(configs.ResponseFail, "参数错误!", &err)
}
// validation
valid := validation.Validation{}
valid.Required(newKnowledgeBase.Title, "title").Message("标题不能为空!")
valid.Required(newKnowledgeBase.Content, "content").Message("内容不能为空!")
valid.Required(newKnowledgeBase.UID, "uid").Message("用户ID不能为空!")
if valid.HasErrors() {
for _, err := range valid.Errors {
c.JSON(configs.ResponseFail, err.Message, &err)
}
}
// is exist title?
oldKnowledgeBase := c.KnowledgeBaseRepository.GetKnowledgeBaseWithTitle(newKnowledgeBase.Title)
if oldKnowledgeBase != nil && oldKnowledgeBase.ID != newKnowledgeBase.ID {
c.JSON(configs.ResponseFail, "标题已存在,请换个标题!", nil)
}
// Platform exist
if platform := c.PlatformRepository.GetPlatform(newKnowledgeBase.Platform); platform == nil {
c.JSON(configs.ResponseFail, "不存在的平台id!", nil)
}
// handle sub title
newKnowledgeBase.SubTitle = strings.Trim(newKnowledgeBase.SubTitle, "|")
if newKnowledgeBase.SubTitle != "" {
newKnowledgeBase.SubTitle = "|" + newKnowledgeBase.SubTitle + "|"
}
// insert
row, err := c.KnowledgeBaseRepository.UpdateParams(newKnowledgeBase.ID, orm.Params{
"Title": newKnowledgeBase.Title,
"SubTitle": newKnowledgeBase.SubTitle,
"Content": newKnowledgeBase.Content,
"Platform": newKnowledgeBase.Platform,
"UpdateAt": time.Now().Unix(),
})
if err != nil || row == 0 {
c.JSON(configs.ResponseFail, "更新失败!", &err)
}
if oldKnowledgeBase != nil {
newKnowledgeBase.CreateAt = oldKnowledgeBase.CreateAt
}
newKnowledgeBase.SubTitle = strings.Trim(newKnowledgeBase.SubTitle, "|")
c.JSON(configs.ResponseSucess, "更新成功!", &newKnowledgeBase)
}
// Delete delete a knowledge Base
func (c *KnowledgeBaseController) Delete() {
id, _ := strconv.ParseInt(c.Ctx.Input.Param(":id"), 10, 64)
num, err := c.KnowledgeBaseRepository.Delete(id)
if err != nil || num == 0 {
c.JSON(configs.ResponseFail, "删除失败!", &err)
}
c.JSON(configs.ResponseSucess, "删除成功!", num)
}
// List quesy list
func (c *KnowledgeBaseController) List() {
// request body
var paginationData *models.PaginationData
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &paginationData); err != nil {
c.JSON(configs.ResponseFail, "参数错误!", &err)
}
// query
paginationData, err := c.KnowledgeBaseRepository.GetKnowledgeBases(paginationData)
if err != nil {
c.JSON(configs.ResponseFail, "查询失败!", &err)
}
c.JSON(configs.ResponseSucess, "查询成功!", &paginationData)
}
package controllers
import (
"encoding/base64"
"encoding/json"
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
"github.com/astaxie/beego/validation"
"kefu_server/im"
"kefu_server/models"
"kefu_server/utils"
"strconv"
"time"
)
// MessageController struct
type MessageController struct {
beego.Controller
}
// List get messages
func (c *MessageController) List() {
o := orm.NewOrm()
messagePaginationData := models.MessagePaginationData{}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &messagePaginationData); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "参数错误!", nil)
c.ServeJSON()
return
}
// service ID
var serviceID int64
if messagePaginationData.Service == 0 {
token := c.Ctx.Input.Header("Authorization")
_auth := models.Auths{Token: token}
if err := o.Read(&_auth, "Token"); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "登录已失效!", nil)
c.ServeJSON()
return
}
admin := models.Admin{ID: _auth.UID}
if err := o.Read(&admin); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "查询失败,用户不存在", err)
c.ServeJSON()
return
}
serviceID = admin.ID
} else {
serviceID = messagePaginationData.Service
}
// Timestamp == 0
if messagePaginationData.Timestamp == 0 {
messagePaginationData.Timestamp = time.Now().Unix()
}
// validation
valid := validation.Validation{}
valid.Required(messagePaginationData.Account, "account").Message("account不能为空!")
valid.Required(messagePaginationData.PageSize, "page_size").Message("page_size不能为空!")
valid.Required(messagePaginationData.Timestamp, "timestamp").Message("timestamp不能为空!")
if valid.HasErrors() {
for _, err := range valid.Errors {
c.Data["json"] = utils.ResponseError(c.Ctx, err.Message, nil)
break
}
c.ServeJSON()
return
}
// join string
qs := o.QueryTable(new(models.Message))
accounts := []int64{messagePaginationData.Account, serviceID}
inExp := "?,?"
// get all robot
robots := im.GetRobots()
for _, robot := range robots {
accounts = append(accounts, robot.ID)
inExp = inExp + ",?"
}
var messages []*models.Message
msgCount, _ := qs.Filter("timestamp__lt", messagePaginationData.Timestamp).Filter("to_account__in", accounts).Filter("from_account__in", accounts).Filter("delete", 0).Count()
// Paging
end := msgCount
start := int(msgCount) - messagePaginationData.PageSize
if start <= 0 {
start = 0
}
if msgCount > 0 {
_, err := o.Raw("SELECT * FROM `message` WHERE to_account IN ("+inExp+") AND `delete` = 0 AND from_account IN ("+inExp+") AND `timestamp` < ? ORDER BY `timestamp` ASC LIMIT ?,?", accounts, accounts, messagePaginationData.Timestamp, start, end).QueryRows(&messages)
_, _ = qs.Filter("from_account", messagePaginationData.Account).Update(orm.Params{"read": 0})
if err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "查询失败!", &err)
c.ServeJSON()
return
}
total, _ := qs.Filter("to_account__in", accounts).Filter("from_account__in", accounts).Filter("delete", 0).Count()
messagePaginationData.List = messages
messagePaginationData.Total = total
} else {
messagePaginationData.List = []models.Message{}
messagePaginationData.Total = 0
}
for index, msg := range messages {
payload, _ := base64.StdEncoding.DecodeString(msg.Payload)
messages[index].Payload = string(payload)
}
if len(im.Robots) > 0 {
im.PushNewContacts(serviceID, im.Robots[0])
}
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "查询成功!", &messagePaginationData)
c.ServeJSON()
}
// RemoveRequestData struct
type RemoveRequestData struct {
FromAccount int64 `json:"from_account"`
ToAccount int64 `json:"to_account"`
Key int64 `json:"key"`
}
// Remove one message
func (c *MessageController) Remove() {
o := orm.NewOrm()
token := c.Ctx.Input.Header("Authorization")
_auth := models.Auths{Token: token}
if err := o.Read(&_auth, "Token"); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "登录已失效!", nil)
c.ServeJSON()
return
}
admin := models.Admin{ID: _auth.UID}
if err := o.Read(&admin); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "无权限操作", err)
c.ServeJSON()
return
}
// request body
removeRequestData := RemoveRequestData{}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &removeRequestData); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "参数错误!", nil)
c.ServeJSON()
return
}
// validation
valid := validation.Validation{}
valid.Required(removeRequestData.ToAccount, "to_account").Message("to_account不能为空!")
valid.Required(removeRequestData.FromAccount, "from_account").Message("from_account不能为空!")
valid.Required(removeRequestData.Key, "key").Message("key不能为空!")
if valid.HasErrors() {
for _, err := range valid.Errors {
c.Data["json"] = utils.ResponseError(c.Ctx, err.Message, nil)
break
}
c.ServeJSON()
return
}
_, err := o.Raw("UPDATE message SET `delete` = 1 WHERE from_account = ? AND to_account = ? AND `key` = ?", removeRequestData.FromAccount, removeRequestData.ToAccount, removeRequestData.Key).Exec()
if err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "删除失败!", &err)
} else {
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "删除成功", nil)
}
c.ServeJSON()
}
// TransferRequestData struct
type TransferRequestData struct {
ToAccount int64 `json:"to_account"` // 转接给谁
UserAccount int64 `json:"user_account"` // 用户ID
}
// Transfer transfer user to user
func (c *MessageController) Transfer() {
o := orm.NewOrm()
token := c.Ctx.Input.Header("Authorization")
_auth := models.Auths{Token: token}
if err := o.Read(&_auth, "Token"); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "登录已失效!", nil)
c.ServeJSON()
return
}
admin := models.Admin{ID: _auth.UID}
if err := o.Read(&admin); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "查询失败,用户不存在", err)
c.ServeJSON()
return
}
// request body
transferRequestData := TransferRequestData{}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &transferRequestData); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "参数错误!", nil)
c.ServeJSON()
return
}
// validation
valid := validation.Validation{}
valid.Required(transferRequestData.ToAccount, "to_account").Message("to_account不能为空!")
valid.Required(transferRequestData.UserAccount, "user_account").Message("user不能为空!")
if valid.HasErrors() {
for _, err := range valid.Errors {
c.Data["json"] = utils.ResponseError(c.Ctx, err.Message, nil)
break
}
c.ServeJSON()
return
}
robot := im.Robots[0]
robotID, _ := strconv.ParseInt(robot.AppAccount(), 10, 64)
type adminData struct {
ID int64 `orm:"column(id)" json:"id"`
NickName string `json:"nickname"`
Avatar string `json:"avatar"`
}
toAdmin := models.Admin{ID: transferRequestData.ToAccount}
if err := o.Read(&toAdmin); err != nil {
c.Data["json"] = utils.ResponseError(c.Ctx, "转接失败,转接客服不存在", nil)
c.ServeJSON()
return
}
toAdminJSON, _ := json.Marshal(adminData{ID: toAdmin.ID, Avatar: toAdmin.Avatar, NickName: toAdmin.NickName})
user := models.User{ID: transferRequestData.UserAccount}
_ = o.Read(&user)
// message
message := models.Message{}
message.BizType = "transfer"
message.FromAccount = transferRequestData.UserAccount
message.Timestamp = time.Now().Unix()
message.TransferAccount = transferRequestData.ToAccount
// Send to forwarder
message.ToAccount = admin.ID
message.Payload = "您将" + user.NickName + "转接给" + toAdmin.NickName
messageJSONOne, _ := json.Marshal(message)
messageStringOne := base64.StdEncoding.EncodeToString([]byte(messageJSONOne))
robot.SendMessage(strconv.FormatInt(admin.ID, 10), []byte(messageStringOne))
im.MessageInto(message, true)
// Send to forwarded customer service
message.ToAccount = transferRequestData.ToAccount
message.Payload = admin.NickName + "将" + user.NickName + "转接给您"
messageJSONTwo, _ := json.Marshal(message)
messageStringTwo := base64.StdEncoding.EncodeToString([]byte(messageJSONTwo))
robot.SendMessage(strconv.FormatInt(transferRequestData.ToAccount, 10), []byte(messageStringTwo))
im.MessageInto(message, true)
// send to user
message.FromAccount = robotID
message.ToAccount = transferRequestData.UserAccount
message.Delete = 1
message.Payload = string(toAdminJSON)
messageJSONThree, _ := json.Marshal(message)
messageString3 := base64.StdEncoding.EncodeToString([]byte(messageJSONThree))
robot.SendMessage(strconv.FormatInt(transferRequestData.UserAccount, 10), []byte(messageString3))
im.MessageInto(message, false)
// Transfer to the library for counting service times
servicesStatistical := models.ServicesStatistical{UserAccount: transferRequestData.UserAccount, ServiceAccount: transferRequestData.ToAccount, TransferAccount: admin.ID, Platform: user.Platform, CreateAt: time.Now().Unix()}
_, _ = o.Insert(&servicesStatistical)
// End the repeater's and user's current session
tk := time.NewTimer(1 * time.Second)
select {
case <-tk.C:
endUsersID := []int64{admin.ID, transferRequestData.UserAccount}
_, _ = o.Raw("UPDATE contact SET is_session_end = 1 WHERE to_account IN(?,?) AND from_account IN(?,?)", endUsersID, endUsersID).Exec()
}
c.Data["json"] = utils.ResponseSuccess(c.Ctx, "转接成功", nil)
c.ServeJSON()
}
package controllers
import (
"encoding/base64"
"encoding/json"
"github.com/astaxie/beego/validation"
"kefu_server/configs"
"kefu_server/im"
"kefu_server/models"
"kefu_server/services"
"kefu_server/utils"
"strconv"
"time"
)
// MessageController struct
type MessageController struct {
BaseController
MessageRepository *services.MessageRepository
}
// Prepare More like construction method
func (c *MessageController) Prepare() {
// init MessageRepository
c.MessageRepository = new(services.MessageRepository)
c.MessageRepository.Init(new(models.Message))
}
// Finish Comparison like destructor
func (c *MessageController) Finish() {}
// List get messages
func (c *MessageController) List() {
messagePaginationData := models.MessagePaginationData{}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &messagePaginationData); err != nil {
c.JSON(configs.ResponseFail, "参数错误!", nil)
}
// service ID
var serviceID int64
if messagePaginationData.Service == 0 {
// GetAuthInfo
auth := c.GetAuthInfo()
serviceID = auth.UID
} else {
serviceID = messagePaginationData.Service
}
// Timestamp == 0
if messagePaginationData.Timestamp == 0 {
messagePaginationData.Timestamp = time.Now().Unix()
}
// validation
valid := validation.Validation{}
valid.Required(messagePaginationData.Account, "account").Message("account不能为空!")
valid.Required(messagePaginationData.PageSize, "page_size").Message("page_size不能为空!")
valid.Required(messagePaginationData.Timestamp, "timestamp").Message("timestamp不能为空!")
if valid.HasErrors() {
for _, err := range valid.Errors {
c.JSON(configs.ResponseFail, err.Message, nil)
}
}
// query message
returnMessagePaginationData, err := c.MessageRepository.GetMessages(serviceID, messagePaginationData)
if err != nil {
c.JSON(configs.ResponseFail, "查询失败!", &err)
}
// push notify update current service contacts list
if len(im.Robots) > 0 {
im.PushNewContacts(serviceID, im.Robots[0])
}
c.JSON(configs.ResponseSucess, "查询成功!", &returnMessagePaginationData)
}
// Remove one message
func (c *MessageController) Remove() {
// request body
removeRequestData := models.RemoveMessageRequestData{}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &removeRequestData); err != nil {
c.JSON(configs.ResponseFail, "参数错误!", nil)
}
// validation
valid := validation.Validation{}
valid.Required(removeRequestData.ToAccount, "to_account").Message("to_account不能为空!")
valid.Required(removeRequestData.FromAccount, "from_account").Message("from_account不能为空!")
valid.Required(removeRequestData.Key, "key").Message("key不能为空!")
if valid.HasErrors() {
for _, err := range valid.Errors {
c.JSON(configs.ResponseFail, err.Message, nil)
}
}
row, err := c.MessageRepository.Delete(removeRequestData)
if err != nil || row == 0 {
c.JSON(configs.ResponseFail, "删除失败!", &err)
}
c.JSON(configs.ResponseSucess, "删除成!", row)
}
// Transfer transfer user to user
func (c *MessageController) Transfer() {
// GetAuthInfo
auth := c.GetAuthInfo()
adminRepository := new(services.AdminRepository)
adminRepository.Init(new(models.Admin))
admin := adminRepository.GetAdmin(auth.UID)
// request body
var transferRequestData *models.TransferRequestData
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &transferRequestData); err != nil {
c.JSON(configs.ResponseFail, "参数错误!", nil)
}
// validation
valid := validation.Validation{}
valid.Required(transferRequestData.ToAccount, "to_account").Message("to_account不能为空!")
valid.Required(transferRequestData.UserAccount, "user_account").Message("user不能为空!")
if valid.HasErrors() {
for _, err := range valid.Errors {
c.JSON(configs.ResponseFail, err.Message, nil)
}
}
robot := im.Robots[0]
robotID, _ := strconv.ParseInt(robot.AppAccount(), 10, 64)
type adminData struct {
ID int64 `orm:"column(id)" json:"id"`
NickName string `json:"nickname"`
Avatar string `json:"avatar"`
}
toAdmin := adminRepository.GetAdmin(transferRequestData.ToAccount)
if toAdmin == nil {
c.JSON(configs.ResponseFail, "转接失败,转接客服不存在!", nil)
}
toAdminJSON, _ := json.Marshal(adminData{ID: toAdmin.ID, Avatar: toAdmin.Avatar, NickName: toAdmin.NickName})
userRepository := new(services.UserRepository)
userRepository.Init(new(models.User))
user := userRepository.GetUser(transferRequestData.UserAccount)
if user == nil {
c.JSON(configs.ResponseFail, "转接失败用户ID不存在!", nil)
}
// message
message := models.Message{}
message.BizType = "transfer"
message.FromAccount = transferRequestData.UserAccount
message.Timestamp = time.Now().Unix()
message.TransferAccount = transferRequestData.ToAccount
// Send to forwarder
message.ToAccount = admin.ID
message.Payload = "您将" + user.NickName + "转接给" + toAdmin.NickName
messageJSONOne, _ := json.Marshal(message)
messageStringOne := base64.StdEncoding.EncodeToString([]byte(messageJSONOne))
robot.SendMessage(strconv.FormatInt(admin.ID, 10), []byte(messageStringOne))
utils.MessageInto(message, true)
// Send to forwarded customer service
message.ToAccount = transferRequestData.ToAccount
message.Payload = admin.NickName + "将" + user.NickName + "转接给您"
messageJSONTwo, _ := json.Marshal(message)
messageStringTwo := base64.StdEncoding.EncodeToString([]byte(messageJSONTwo))
robot.SendMessage(strconv.FormatInt(transferRequestData.ToAccount, 10), []byte(messageStringTwo))
utils.MessageInto(message, true)
// send to user
message.FromAccount = robotID
message.ToAccount = transferRequestData.UserAccount
message.Delete = 1
message.Payload = string(toAdminJSON)
messageJSONThree, _ := json.Marshal(message)
messageString3 := base64.StdEncoding.EncodeToString([]byte(messageJSONThree))
robot.SendMessage(strconv.FormatInt(transferRequestData.UserAccount, 10), []byte(messageString3))
utils.MessageInto(message, false)
// Transfer to the library for counting service times
servicesStatistical := models.ServicesStatistical{UserAccount: transferRequestData.UserAccount, ServiceAccount: transferRequestData.ToAccount, TransferAccount: admin.ID, Platform: user.Platform, CreateAt: time.Now().Unix()}
statisticalRepository := new(services.StatisticalRepository)
statisticalRepository.Init(new(models.ServicesStatistical))
_, err := statisticalRepository.Add(&servicesStatistical)
if err != nil {
}
// End the repeater's and user's current session
tk := time.NewTimer(1 * time.Second)
select {
case <-tk.C:
usersID := []int64{admin.ID, transferRequestData.UserAccount}
contactRepository := new(services.ContactRepository)
contactRepository.Init(new(models.Contact))
_, err := contactRepository.UpdateIsSessionEnd(usersID, 1)
if err != nil {
}
}
c.JSON(configs.ResponseSucess, "转接成功!", nil)
}
......@@ -403,7 +403,7 @@ func (c *PublicController) PushMessage() {
msgContent, _ := base64.StdEncoding.DecodeString(pushMessage.Payload)
msgContent, _ = base64.StdEncoding.DecodeString(string(msgContent))
json.Unmarshal(msgContent, &getMessage)
im.MessageInto(getMessage, false)
utils.MessageInto(getMessage, false)
c.ServeJSON()
}
......
......@@ -4,6 +4,7 @@ import (
"encoding/base64"
"encoding/json"
"kefu_server/models"
"kefu_server/utils"
"strconv"
"strings"
"time"
......@@ -84,7 +85,7 @@ func MessageP2P(message models.Message) {
intoMessage.Read = 1
}
}
MessageInto(intoMessage, isKF)
utils.MessageInto(intoMessage, isKF)
if isKF {
PushNewContacts(intoMessage.ToAccount, robot)
}
......@@ -220,7 +221,7 @@ func MessageP2P(message models.Message) {
newMsgBase64 = base64.StdEncoding.EncodeToString([]byte(newMsgJSON))
// 消息入库
MessageInto(newMsg, true)
utils.MessageInto(newMsg, true)
robot.SendMessage(strconv.FormatInt(admin.ID, 10), []byte(newMsgBase64))
newMsg.FromAccount = robotID
newMsg.ToAccount = message.FromAccount
......@@ -238,7 +239,7 @@ func MessageP2P(message models.Message) {
newMsgBase64 = base64.StdEncoding.EncodeToString([]byte(newMsgJSON))
// 消息入库
MessageInto(newMsg, true)
utils.MessageInto(newMsg, true)
robot.SendMessage(strconv.FormatInt(admin.ID, 10), []byte(newMsgBase64))
robot.SendMessage(strconv.FormatInt(message.FromAccount, 10), []byte(newMsgBase64))
......@@ -314,6 +315,6 @@ func MessageP2P(message models.Message) {
robot.SendMessage(strconv.FormatInt(message.FromAccount, 10), []byte(messageString))
// 消息入库
MessageInto(callbackMessage, false)
utils.MessageInto(callbackMessage, false)
}
......@@ -16,6 +16,7 @@ import (
"kefu_server/im"
"kefu_server/models"
_ "kefu_server/routers"
"kefu_server/utils"
"strconv"
"time"
)
......@@ -130,7 +131,7 @@ func appTask() {
messageJSON, _ = json.Marshal(message)
messageString = base64.StdEncoding.EncodeToString([]byte(messageJSON))
robot.SendMessage(strconv.FormatInt(contact.ToAccount, 10), []byte(messageString))
im.MessageInto(message, true)
utils.MessageInto(message, true)
// 超时后消息
// 数据库获取机器人配置信息
......@@ -180,9 +181,9 @@ func main() {
initLog()
// 启动任务
appTask()
toolbox.StartTask()
defer toolbox.StopTask()
// appTask()
// toolbox.StartTask()
// defer toolbox.StopTask()
/// 静态文件配置
beego.SetStaticPath("/", "public/client")
......@@ -193,7 +194,7 @@ func main() {
beego.ErrorController(&controllers.ErrorController{})
// 启动机器人
im.RobotInit()
// im.RobotInit()
// 初始化beeGo
beego.Run()
......
package models
// RemoveMessageRequestData struct
type RemoveMessageRequestData struct {
FromAccount int64 `json:"from_account"`
ToAccount int64 `json:"to_account"`
Key int64 `json:"key"`
}
package models
import "kefu_server/configs"
// Response struct
type Response struct {
Code int `json:"code"` // 错误类型
Message string `json:"message"` // 信息
Data interface{} `json:"data"` // 任意类型
Code configs.ResponseStatusType `json:"code"` // 错误类型
Message string `json:"message"` // 信息
Data interface{} `json:"data"` // 任意类型
}
package models
// TransferRequestData struct
type TransferRequestData struct {
ToAccount int64 `json:"to_account"` // 转接给谁
UserAccount int64 `json:"user_account"` // 用户ID
}
......@@ -132,7 +132,7 @@ func init() {
beego.NSBefore(filters.FilterToken),
beego.NSRouter("/?:id", &controllers.ContactController{}),
beego.NSRouter("/list", &controllers.ContactController{}, "get:GetContacts"),
beego.NSRouter("/clear", &controllers.ContactController{}, "delete:Clear"),
beego.NSRouter("/clear", &controllers.ContactController{}, "delete:DeleteAll"),
),
// platform
......
package services
import (
"kefu_server/models"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
)
// AdminRepositoryInterface interface
type AdminRepositoryInterface interface {
GetAdmin(id int64) *models.Admin
GetAdminWithUserName(userName string) *models.Admin
UpdateParams(id int64, params *orm.Params) (int64, error)
Add(admin *models.Admin, col1 string) (bool, int64, error)
Delete(id int64) (int64, error)
GetAdmins(request *AdminPaginationData) (*AdminPaginationData, error)
}
// AdminPaginationData a struct
type AdminPaginationData struct {
PageSize int `json:"page_size"`
PageOn int `json:"page_on"`
Keyword string `json:"keyword"`
Total int64 `json:"total"`
Online int `json:"online"`
List interface{} `json:"list"`
}
// UpdatePasswordRequest admin password
type UpdatePasswordRequest struct {
OldPassword string `json:"old_password"`
NewPassword string `json:"new_password"`
EnterPassword string `json:"enter_password"`
}
// AdminRepository struct
type AdminRepository struct {
BaseRepository
}
// GetAdmin get one admin with id
func (r *AdminRepository) GetAdmin(id int64) *models.Admin {
var admin models.Admin
if err := r.q.Filter("id", id).One(&admin); err != nil {
logs.Warn("GetAdmin get one admin with id------------", err)
return nil
}
return &admin
}
// GetAdminWithUserName get one admin with username
func (r *AdminRepository) GetAdminWithUserName(userName string) *models.Admin {
var admin models.Admin
if err := r.q.Filter("UserName", userName).One(&admin); err != nil {
logs.Warn("GetAdminWithUserName get one admin with username------------", err)
return nil
}
return &admin
}
// UpdateParams update admin
func (r *AdminRepository) UpdateParams(id int64, params orm.Params) (int64, error) {
index, err := r.q.Filter("id", id).Update(params)
if err != nil {
logs.Warn("UpdateParams update admin------------", err)
}
return index, err
}
// Add create a admin
func (r *AdminRepository) Add(admin *models.Admin, col1 string) (bool, int64, error) {
_bool, index, err := r.o.ReadOrCreate(admin, col1)
if err != nil {
logs.Warn("Add create a admin------------", err)
}
return _bool, index, err
}
// Delete delete a admin
func (r *AdminRepository) Delete(id int64) (int64, error) {
index, err := r.q.Filter("id", id).Delete()
if err != nil {
logs.Warn("Delete delete a admin------------", err)
}
return index, err
}
// GetAdmins get admin list
func (r *AdminRepository) GetAdmins(request *AdminPaginationData) (*AdminPaginationData, error) {
var lists []models.Admin
qs := r.q.Filter("nickname__icontains", request.Keyword)
if request.Online == 0 {
qs = qs.Filter("online", 0)
}
if request.Online == 1 {
qs = qs.Filter("online", 1)
}
if request.PageSize < MinPageSize {
request.PageSize = MinPageSize
}
if request.PageSize > MaxPageSize {
request.PageSize = MaxPageSize
}
if _, err := qs.OrderBy("-root", "id").Limit(request.PageSize, (request.PageOn-1)*request.PageSize).All(&lists); err != nil {
logs.Warn("GetAdmins get admin list------------", err)
return nil, err
}
total, _ := qs.Count()
for index := range lists {
lists[index].Password = "******"
}
request.Total = total
request.List = &lists
return request, nil
}
package services
import (
"kefu_server/models"
"github.com/astaxie/beego/logs"
)
// AuthTypesRepositoryInterface interface
type AuthTypesRepositoryInterface interface {
GetAuthType(id int64) *models.AuthTypes
}
// AuthTypesRepository struct
type AuthTypesRepository struct {
BaseRepository
}
// GetAuthType get a authType
func (r *AuthTypesRepository) GetAuthType(id int64) *models.AuthTypes {
var authType models.AuthTypes
if err := r.q.Filter("id", id).One(&authType); err != nil {
logs.Warn("GetAuthType get a authType------------", err)
return nil
}
return &authType
}
package services
import (
"kefu_server/models"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
)
// AuthsRepositoryInterface interface
type AuthsRepositoryInterface interface {
GetAuthInfo(token string) *models.Auths
GetAuthInfoWithTypeAndUID(authType int64, uid int64) *models.Auths
GetAdminOnlineCount(uid int64) int64
Delete(id int64) (int64, error)
Add(id *models.Auths) (int64, error)
UpdateParams(id int64, params orm.Params) (int64, error)
}
// AuthsRepository struct
type AuthsRepository struct {
BaseRepository
}
// GetAuthInfo get a auth info
func (r *AuthsRepository) GetAuthInfo(token string) *models.Auths {
var auth models.Auths
if err := r.q.Filter("token", token).One(&auth); err != nil {
logs.Warn("GetAuthInfo get a auth info------------", err)
return nil
}
return &auth
}
// GetAuthInfoWithTypeAndUID get a auth info with type and uid
func (r *AuthsRepository) GetAuthInfoWithTypeAndUID(authType int64, uid int64) *models.Auths {
var auth models.Auths
if err := r.q.Filter("auth_type", authType).Filter("uid", uid).One(&auth); err != nil {
logs.Warn("GetAuthInfoWithTypeAndUID get a auth info with type and uid------------", err)
return nil
}
return &auth
}
// GetAdminOnlineCount get admin anth count
func (r *AuthsRepository) GetAdminOnlineCount(uid int64) int64 {
count, err := r.q.Filter("uid", uid).Count()
if err != nil {
logs.Warn(" GetAdminOnlineCount get admin anth count------------", err)
return 0
}
return count
}
// Delete delete a auth
func (r *AuthsRepository) Delete(id int64) (int64, error) {
row, err := r.q.Filter("id", id).Delete()
if err != nil {
logs.Warn("Delete delete a auth------------", err)
return 0, err
}
return row, nil
}
// UpdateParams update admin
func (r *AuthsRepository) UpdateParams(id int64, params orm.Params) (int64, error) {
index, err := r.q.Filter("id", id).Update(params)
if err != nil {
logs.Warn("UpdateParams update admin------------", err)
}
return index, err
}
// Add add auth
func (r *AuthsRepository) Add(auth *models.Auths) (int64, error) {
index, err := r.o.Insert(auth)
if err != nil {
logs.Warn("Add add auth------------", err)
}
return index, err
}
package services
import (
"github.com/astaxie/beego/orm"
)
// const val
var (
MinPageSize = 1
MaxPageSize = 50
)
// BaseRepository struct
// o is orm Object
// q is orm QuerySeter Object
type BaseRepository struct {
q orm.QuerySeter
o orm.Ormer
}
// Init BaseRepository
// Subsets must pass specific models join
func (r *BaseRepository) Init(ptrStructOrTableName interface{}) {
var o = orm.NewOrm()
var querySeter = o.QueryTable(ptrStructOrTableName)
r.o = o
r.q = querySeter
}
package services
import (
"kefu_server/models"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
)
// CompanyRepositoryInterface interface
type CompanyRepositoryInterface interface {
GetCompany(id int64) *models.Company
UpdateParams(id int64, params *orm.Params) (int64, error)
}
// CompanyRepository struct
type CompanyRepository struct {
BaseRepository
}
// GetCompany get one company
func (r *CompanyRepository) GetCompany(id int64) *models.Company {
var company models.Company
if err := r.q.Filter("id", id).One(&company); err != nil {
logs.Warn("GetCompany get one company------------", err)
return nil
}
return &company
}
// UpdateParams update company
func (r *CompanyRepository) UpdateParams(id int64, params orm.Params) (int64, error) {
index, err := r.q.Filter("id", id).Update(params)
if err != nil {
logs.Warn("UpdateParams update company------------", err)
}
return index, err
}
package services
import (
"encoding/base64"
"kefu_server/models"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
)
// ContactRepositoryInterface interface
type ContactRepositoryInterface interface {
GetContact(id int64) *models.Contact
GetContacts(uid int64) ([]models.ContactData, error)
UpdateIsSessionEnd(usersID []int64, isSessionEnd int) (int64, error)
UpdateParams(id int64, params *orm.Params) (int64, error)
Delete(id int64, uid int64) (int64, error)
DeleteAll(uid int64) (int64, error)
Add(contact *models.Contact) (int64, error)
GetContactWithIds(ids ...int64) (*models.Contact, error)
}
// ContactRepository struct
type ContactRepository struct {
BaseRepository
}
// Add add a Contact
func (r *ContactRepository) Add(contact *models.Contact) (int64, error) {
row, err := r.o.Insert(&contact)
if err != nil {
logs.Warn("Add add a Contact------------", err)
}
return row, err
}
// GetContact get one Contact
func (r *ContactRepository) GetContact(id int64) *models.Contact {
var contact models.Contact
if err := r.q.Filter("id", id).One(&contact); err != nil {
logs.Warn("Contact get one Contact------------", err)
return nil
}
return &contact
}
// GetContactWithIds get one Contact with ids
func (r *ContactRepository) GetContactWithIds(ids ...int64) (*models.Contact, error) {
var contact *models.Contact
err := r.q.Filter("from_account__in", ids).Filter("to_account__in", ids).One(&contact)
if err != nil {
logs.Warn("GetContactWithIds get one Contact with ids------------", err)
}
return contact, err
}
// UpdateIsSessionEnd update
func (r *ContactRepository) UpdateIsSessionEnd(usersID []int64, isSessionEnd int) (int64, error) {
res, err := r.o.Raw("UPDATE contact SET is_session_end = 1 WHERE to_account IN(?,?) AND from_account IN(?,?)", usersID, usersID).Exec()
rows, _ := res.RowsAffected()
if err != nil {
logs.Warn(" UpdateIsSessionEnd update------------", err)
return 0, err
}
return rows, nil
}
// GetContacts get Contacts
func (r *ContactRepository) GetContacts(uid int64) ([]models.ContactData, error) {
var contactData []models.ContactData
_, err := r.o.Raw("SELECT c.id AS cid,c.to_account,c.is_session_end, c.last_message,c.last_message_type,c.from_account, c.create_at AS contact_create_at,u.*, IFNULL(m.`count`,0) AS `read` FROM `contact` c LEFT JOIN `user` u ON c.from_account = u.id LEFT JOIN (SELECT to_account,from_account, COUNT(*) as `count` FROM message WHERE `read` = 1 GROUP BY to_account,from_account) m ON m.to_account = c.to_account AND m.from_account = c.from_account WHERE c.to_account = ? AND c.delete = 0 ORDER BY c.create_at DESC", uid).QueryRows(&contactData)
if err != nil {
logs.Warn("GetContacts get Contacts------------", err)
return nil, err
}
// content base 64 decode
for index, contact := range contactData {
payload, _ := base64.StdEncoding.DecodeString(contact.LastMessage)
contactData[index].LastMessage = string(payload)
}
return contactData, nil
}
// Delete delete a Contact
func (r *ContactRepository) Delete(id int64, uid int64) (int64, error) {
res, err := r.o.Raw("UPDATE `contact` SET `delete` = 1 WHERE id = ? AND to_account = ?", id, uid).Exec()
rows, _ := res.RowsAffected()
if err != nil {
logs.Warn("GetContacts get Contacts err------------", err)
}
return rows, err
}
// DeleteAll delete all Contact
func (r *ContactRepository) DeleteAll(uid int64) (int64, error) {
res, err := r.o.Raw("UPDATE `contact` SET `delete` = 1 WHERE to_account = ?", uid).Exec()
rows, _ := res.RowsAffected()
if err != nil {
logs.Warn("DeleteAll delete all Contact error------------", err)
}
return rows, err
}
// UpdateParams update contact
func (r *ContactRepository) UpdateParams(id int64, params orm.Params) (int64, error) {
index, err := r.q.Filter("id", id).Update(params)
if err != nil {
logs.Warn("UpdateParams update contact------------", err)
}
return index, err
}
package services
import (
"kefu_server/models"
"strings"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
)
// KnowledgeBaseRepositoryInterface interface
type KnowledgeBaseRepositoryInterface interface {
GetKnowledgeBase(id int64) *models.KnowledgeBase
GetKnowledgeBases(request models.PaginationData) (*models.PaginationData, error)
GetKnowledgeBaseWithTitle(title string) *models.KnowledgeBase
Add(knowledgeBase *models.KnowledgeBase, col1 string) (bool, int64, error)
UpdateParams(id int64, params *orm.Params) (int64, error)
Delete(id int64) (int64, error)
}
// KnowledgeBaseRepository struct
type KnowledgeBaseRepository struct {
BaseRepository
}
// Add create a knowledgeBase
func (r *KnowledgeBaseRepository) Add(knowledgeBase *models.KnowledgeBase, col1 string) (bool, int64, error) {
knowledgeBase.SubTitle = strings.Trim(knowledgeBase.SubTitle, "|")
if knowledgeBase.SubTitle != "" {
knowledgeBase.SubTitle = "|" + knowledgeBase.SubTitle + "|"
}
_bool, index, err := r.o.ReadOrCreate(knowledgeBase, col1)
if err != nil {
logs.Warn("Add create a Platform------------", err)
}
return _bool, index, err
}
// UpdateParams update knowledgeBase
func (r *KnowledgeBaseRepository) UpdateParams(id int64, params orm.Params) (int64, error) {
index, err := r.q.Filter("id", id).Update(params)
if err != nil {
logs.Warn("UpdateParams update knowledgeBase------------", index, err)
}
return index, err
}
// GetKnowledgeBase get one KnowledgeBase
func (r *KnowledgeBaseRepository) GetKnowledgeBase(id int64) *models.KnowledgeBase {
var base models.KnowledgeBase
if err := r.q.Filter("id", id).One(&base); err != nil {
logs.Warn("GetUser get one KnowledgeBase------------", err)
return nil
}
base.SubTitle = strings.Trim(base.SubTitle, "|")
return &base
}
// GetKnowledgeBases get one KnowledgeBases
func (r *KnowledgeBaseRepository) GetKnowledgeBases(request *models.PaginationData) (*models.PaginationData, error) {
if request.PageSize < MinPageSize {
request.PageSize = MinPageSize
}
if request.PageSize > MaxPageSize {
request.PageSize = MaxPageSize
}
// query
var lists []models.KnowledgeBase
if _, err := r.q.OrderBy("-create_at").Limit(request.PageSize).Offset((request.PageOn - 1) * request.PageSize).All(&lists); err != nil {
logs.Warn("GetKnowledgeBases get one KnowledgeBases------------", err)
return nil, err
}
if request.PageSize < MinPageSize {
request.PageSize = MinPageSize
}
if request.PageSize > MaxPageSize {
request.PageSize = MaxPageSize
}
total, _ := r.q.Count()
for index := range lists {
lists[index].SubTitle = strings.Trim(lists[index].SubTitle, "|")
}
request.Total = total
request.List = &lists
return request, nil
}
// GetKnowledgeBaseWithTitle get one KnowledgeBase with title
func (r *KnowledgeBaseRepository) GetKnowledgeBaseWithTitle(title string) *models.KnowledgeBase {
var base models.KnowledgeBase
if err := r.q.Filter("title", title).One(&base); err != nil {
logs.Warn("GetKnowledgeBaseWithTitle get one KnowledgeBase with title------------", err)
return nil
}
base.SubTitle = strings.Trim(base.SubTitle, "|")
return &base
}
// Delete delete a KnowledgeBase
func (r *KnowledgeBaseRepository) Delete(id int64) (int64, error) {
index, err := r.q.Filter("id", id).Delete()
if err != nil {
logs.Warn("Delete delete a KnowledgeBase------------", err)
}
return index, err
}
package services
import (
"encoding/base64"
"kefu_server/models"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
)
// MessageRepositoryInterface interface
type MessageRepositoryInterface interface {
GetMessages(serviceID int64, messagePaginationData models.MessagePaginationData) (*models.MessagePaginationData, error)
Delete(removeRequestData models.RemoveMessageRequestData) (int64, error)
Add(message *models.Message) (int64, error)
}
// MessageRepository struct
type MessageRepository struct {
BaseRepository
}
// Add add a message
func (r *MessageRepository) Add(message *models.Message) (int64, error) {
row, err := r.o.Insert(&message)
if err != nil {
logs.Warn("Add add a message------------", err)
}
return row, err
}
// Delete delete a message
func (r *MessageRepository) Delete(removeRequestData models.RemoveMessageRequestData) (int64, error) {
res, err := r.o.Raw("UPDATE message SET `delete` = 1 WHERE from_account = ? AND to_account = ? AND `key` = ?", removeRequestData.FromAccount, removeRequestData.ToAccount, removeRequestData.Key).Exec()
row, _ := res.RowsAffected()
if err != nil {
return 0, err
}
return row, nil
}
// GetMessages get one service message list
func (r *MessageRepository) GetMessages(serviceID int64, messagePaginationData models.MessagePaginationData) (*models.MessagePaginationData, error) {
var err error
var msgCount int64
var messages []*models.Message
// join string
accounts := []int64{messagePaginationData.Account, serviceID}
inExp := "?,?"
// get all robot
robotRepository := new(RobotRepository)
robotRepository.Init(new(models.Robot))
robots, err := robotRepository.GetRobots()
if err != nil {
logs.Warn("GetMessages get one service message list0------------", err)
}
for _, robot := range robots {
accounts = append(accounts, robot.ID)
inExp = inExp + ",?"
}
msgCount, err = r.q.Filter("timestamp__lt", messagePaginationData.Timestamp).Filter("to_account__in", accounts).Filter("from_account__in", accounts).Filter("delete", 0).Count()
if err != nil {
logs.Warn("GetMessages get one service message list1------------", err)
}
// Paging
end := msgCount
start := int(msgCount) - messagePaginationData.PageSize
if start <= 0 {
start = 0
}
if msgCount > 0 {
_, err = r.o.Raw("SELECT * FROM `message` WHERE to_account IN ("+inExp+") AND `delete` = 0 AND from_account IN ("+inExp+") AND `timestamp` < ? ORDER BY `timestamp` ASC LIMIT ?,?", accounts, accounts, messagePaginationData.Timestamp, start, end).QueryRows(&messages)
if err != nil {
logs.Warn("GetMessages get one service message list2------------", err)
return nil, err
}
_, err = r.q.Filter("from_account", messagePaginationData.Account).Update(orm.Params{"read": 0})
if err != nil {
logs.Warn("GetMessages get one service message list3------------", err)
return nil, err
}
total, _ := r.q.Filter("to_account__in", accounts).Filter("from_account__in", accounts).Filter("delete", 0).Count()
messagePaginationData.List = messages
messagePaginationData.Total = total
} else {
messagePaginationData.List = []models.Message{}
messagePaginationData.Total = 0
}
for index, msg := range messages {
payload, _ := base64.StdEncoding.DecodeString(msg.Payload)
messages[index].Payload = string(payload)
}
return &messagePaginationData, nil
}
package services
import (
"kefu_server/models"
"github.com/astaxie/beego/logs"
)
// PlatformRepositoryInterface interface
type PlatformRepositoryInterface interface {
GetPlatform(id int64) *models.Platform
Add(platform *models.Platform, col1 string) (bool, int64, error)
}
//PlatformRepository struct
type PlatformRepository struct {
BaseRepository
}
// Add create a Platform
func (r *PlatformRepository) Add(platform *models.Platform, col1 string) (bool, int64, error) {
_bool, index, err := r.o.ReadOrCreate(&platform, col1)
if err != nil {
logs.Warn("Add create a Platform------------", err)
}
return _bool, index, err
}
// GetPlatform get one platform
func (r *PlatformRepository) GetPlatform(id int64) *models.Platform {
var platform models.Platform
if err := r.q.Filter("id", id).One(&platform); err != nil {
logs.Warn("GetPlatform get one platform------------", err)
return nil
}
return &platform
}
package services
import (
"kefu_server/models"
"strings"
"github.com/astaxie/beego/logs"
)
// RobotRepositoryInterface interface
type RobotRepositoryInterface interface {
GetRobot(id int64) *models.Robot
GetRobots() ([]models.Robot, error)
GetRobotWithInIds(ids ...int64) ([]models.Robot, error)
}
// RobotRepository struct
type RobotRepository struct {
BaseRepository
}
// GetRobots get Robots
func (r *RobotRepository) GetRobots() ([]models.Robot, error) {
var robots []models.Robot
if _, err := r.q.OrderBy("-create_at").All(&robots); err != nil {
logs.Warn("GetRobot get one Robot------------", err)
return nil, err
}
for index := range robots {
robots[index].Artificial = strings.Trim(robots[index].Artificial, "|")
}
return robots, nil
}
// GetRobot get one Robot
func (r *RobotRepository) GetRobot(id int64) *models.Robot {
var robot models.Robot
if err := r.q.Filter("id", id).One(&robot); err != nil {
logs.Warn("GetRobot get one Robot------------", err)
return nil
}
return &robot
}
// GetRobotWithInIds get one Robot with in() ids
func (r *RobotRepository) GetRobotWithInIds(ids ...int64) ([]models.Robot, error) {
var robots []models.Robot
_, err := r.o.Raw("SELECT * FROM robot WHERE id IN(?, ?)", ids).QueryRows(&robots)
if err != nil {
logs.Warn("GetRobot get one Robot------------", err)
}
return robots, err
}
package services
import (
"errors"
"kefu_server/models"
"math"
"time"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
)
// StatisticalRepositoryInterface interface
type StatisticalRepositoryInterface interface {
Add(servicesStatistical *models.ServicesStatistical) (int64, error)
GetStatisticals(startDate string, endDate string) (map[string]interface{}, error)
GetTodayActionStatistical(startDate string, endDate string) ([]orm.Params, error)
}
// StatisticalRepository struct
type StatisticalRepository struct {
BaseRepository
}
// Add add statistical
func (r *StatisticalRepository) Add(servicesStatistical *models.ServicesStatistical) (int64, error) {
id, err := r.o.Insert(&servicesStatistical)
if err != nil {
logs.Warn("Add add statistical------------", err)
}
return id, err
}
// GetStatisticals get statistical
func (r *StatisticalRepository) GetStatisticals(startDate string, endDate string) (map[string]interface{}, error) {
// transform date
var oneDaySecond float64 = 86400
layoutDate := "2006-01-02 15:04:05"
loc, _ := time.LoadLocation("Local")
dateStartString := startDate + " 00:00:00"
dateEndString := endDate + " 23:59:59"
dateStart, _ := time.ParseInLocation(layoutDate, dateStartString, loc)
dateEnd, _ := time.ParseInLocation(layoutDate, dateEndString, loc)
k := dateEnd.Unix() - dateStart.Unix()
maxDay := int(math.Ceil(float64(k) / oneDaySecond))
if maxDay < 1 || maxDay >= 32 {
logs.Warn("GetStatisticals get statistical | 日期有误,最大只能查询一个月以内~------------", nil)
return nil, errors.New("日期有误,最大只能查询一个月以内~")
}
countsArr := map[string]interface{}{}
// Count customer service access
var membersData []orm.Params
_, err := r.o.Raw("SELECT a.id, a.username, a.nickname, IFNULL(s.count,0) as count FROM `admin` a LEFT JOIN (SELECT service_account,COUNT(*) AS count FROM services_statistical WHERE `create_at` BETWEEN ? AND ? GROUP BY service_account) s ON a.id = s.service_account ORDER BY a.id", dateStart.Unix(), dateEnd.Unix()).Values(&membersData)
if err != nil {
logs.Warn("GetStatisticals get statistical | Count customer service access------------", err)
return nil, err
}
countsArr["members"] = membersData
// Count the traffic of each channel
var statisticalData []interface{}
for i := 0; i < maxDay; i++ {
var statisticalTemp []orm.Params
increment := int64(i) * int64(oneDaySecond)
start := dateStart.Unix() + increment
end := start + int64(oneDaySecond)
if i == maxDay-1 {
end = dateEnd.Unix()
}
_, err := r.o.Raw("SELECT p.id, p.title, IFNULL(s.count,0) as count FROM `platform` p LEFT JOIN (SELECT platform,COUNT(*) AS count FROM `services_statistical` WHERE `create_at` BETWEEN ? AND ? GROUP BY platform) s ON p.id = s.platform ORDER BY p.id", start, end).Values(&statisticalTemp)
if err != nil {
logs.Warn("GetStatisticals get statistical |Count the traffic of each channel------------", nil)
return nil, err
}
day := time.Unix(start, 0).Format("2006-01-02")
statisticalArrItem := map[string]interface{}{}
statisticalArrItem["date"] = day
statisticalArrItem["list"] = statisticalTemp
statisticalData = append(statisticalData, statisticalArrItem)
}
countsArr["statistical"] = statisticalData
return countsArr, nil
}
// GetTodayActionStatistical get Today Action Statistical
func (r *StatisticalRepository) GetTodayActionStatistical(startDate string, endDate string) ([]orm.Params, error) {
// transform date
layoutDate := "2006-01-02 15:04:05"
loc, _ := time.LoadLocation("Local")
dateStartString := startDate + " 00:00:00"
dateEndString := endDate + " 23:59:59"
dateStart, _ := time.ParseInLocation(layoutDate, dateStartString, loc)
dateEnd, _ := time.ParseInLocation(layoutDate, dateEndString, loc)
var statisticalData []orm.Params
_, err := r.o.Raw("SELECT p.id platform,p.title, IFNULL(u.count,0) AS `count` FROM platform as p LEFT JOIN (SELECT platform,COUNT(*) AS count FROM `user` WHERE last_activity BETWEEN ? AND ? GROUP BY platform) u ON p.id = u.platform", dateStart.Unix(), dateEnd.Unix()).Values(&statisticalData)
if err != nil {
logs.Warn("GetTodayActionStatistical get Today Action Statistical------------", err)
return nil, err
}
return statisticalData, nil
}
package services
import (
"kefu_server/models"
"github.com/astaxie/beego/logs"
)
// UserRepositoryInterface interface
type UserRepositoryInterface interface {
GetUser(id int64) *models.User
}
// UserRepository struct
type UserRepository struct {
BaseRepository
}
// GetUser get one User
func (r *UserRepository) GetUser(id int64) *models.User {
var user models.User
if err := r.q.Filter("id", id).One(&user); err != nil {
logs.Warn("GetUser get one User------------", err)
return nil
}
return &user
}
......@@ -2,7 +2,6 @@ package utils
import (
"io/ioutil"
"kefu_server/models"
"math/rand"
"net/http"
"strings"
......@@ -32,14 +31,21 @@ func GetRandomUserAgent() string {
return userAgentList[r.Intn(len(userAgentList))]
}
// HTTPResponse struct
type HTTPResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
// HTTPRequest ...
// url 访问的链接
// method post, get 等
// data body 数据
// token 授权token
func HTTPRequest(url string, method string, bodyData string, token string) *models.Response {
func HTTPRequest(url string, method string, bodyData string, token string) *HTTPResponse {
client := &http.Client{}
response := new(models.Response)
response := new(HTTPResponse)
req, err := http.NewRequest(method, url, strings.NewReader(bodyData))
if err != nil {
response.Code = 500
......
package im
package utils
import (
"encoding/base64"
"kefu_server/models"
"kefu_server/services"
"strconv"
"time"
......@@ -11,18 +12,20 @@ import (
// MessageInto push message
func MessageInto(message models.Message, isKF bool) {
// orm instance
o := orm.NewOrm()
// 不处理的类型
if message.BizType == "contacts" || message.BizType == "pong" || message.BizType == "welcome" || message.BizType == "into" || message.BizType == "search_knowledge" {
return
}
// init MessageRepository
messageRepository := new(services.MessageRepository)
messageRepository.Init(new(models.Message))
// 判断是否是撤回消息(软删除)
if message.BizType == "cancel" {
key, _ := strconv.ParseInt(message.Payload, 10, 64)
_, _ = o.Raw("UPDATE message SET `delete` = 1 WHERE from_account = ? AND to_account = ? AND `key` = ?", message.FromAccount, message.ToAccount, key).Exec()
_, _ = messageRepository.Delete(models.RemoveMessageRequestData{FromAccount: message.FromAccount, ToAccount: message.ToAccount, Key: key})
}
// message create time
......@@ -35,13 +38,16 @@ func MessageInto(message models.Message, isKF bool) {
if !(message.BizType == "handshake") {
if !isKF {
// init UserRepository
userRepository := new(services.UserRepository)
userRepository.Init(new(models.User))
// 默认已读消息
message.Read = 0
user := models.User{ID: message.ToAccount}
if err := o.Read(&user); err == nil && user.Online == 0 {
user := userRepository.GetUser(message.ToAccount)
if user != nil && user.Online == 0 {
message.Read = 1
}
if user.IsWindow == 0 {
if user != nil && user.IsWindow == 0 {
message.Read = 1
}
}
......@@ -52,37 +58,43 @@ func MessageInto(message models.Message, isKF bool) {
}
// 消息入库
_, _ = o.Insert(&message)
_, _ = messageRepository.Add(&message)
}
// 判断是否和机器人对话(不处理聊天列表)
var r []orm.Params
robotCount, _ := o.Raw("SELECT * FROM robot WHERE id IN(?, ?)", message.ToAccount, message.FromAccount).Values(&r)
if robotCount > 0 {
// init RobotRepository
robotRepository := new(services.RobotRepository)
robotRepository.Init(new(models.Robot))
// 判断是否机器人对话(不处理聊天列表)
if rbts, _ := robotRepository.GetRobotWithInIds(message.ToAccount, message.FromAccount); len(rbts) > 0 {
return
}
// init ContactRepository
contactRepository := new(services.ContactRepository)
contactRepository.Init(new(models.Contact))
// 处理客服聊天列表
var contact models.Contact
qs := o.QueryTable(new(models.Contact))
if err := qs.Filter("from_account__in", message.FromAccount, message.ToAccount).Filter("to_account__in", message.ToAccount, message.FromAccount).One(&contact); err != nil {
if contact, err := contactRepository.GetContactWithIds(message.ToAccount, message.FromAccount); err != nil {
contact.ToAccount = message.ToAccount
contact.FromAccount = message.FromAccount
contact.LastMessageType = message.BizType
contact.CreateAt = time.Now().Unix()
contact.LastMessage = message.Payload
o.Insert(&contact)
_, _ = contactRepository.Add(contact)
} else {
contact.LastMessageType = message.BizType
contact.CreateAt = time.Now().Unix()
contact.LastMessage = message.Payload
contact.IsSessionEnd = 0
contact.Delete = 0
isSessionEnd := 0
if message.BizType == "end" || message.BizType == "timeout" {
contact.IsSessionEnd = 1
isSessionEnd = 1
}
o.Update(&contact)
_, _ = contactRepository.UpdateParams(contact.ID, orm.Params{
"LastMessageType": message.BizType,
"CreateAt": time.Now().Unix(),
"LastMessage": message.Payload,
"IsSessionEnd": isSessionEnd,
"Delete": 0,
})
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment