Commit 735ba425 by chenxianqi

update code

parent 24286a8f
...@@ -100,7 +100,7 @@ func (c *PublicController) Register() { ...@@ -100,7 +100,7 @@ func (c *PublicController) Register() {
if user != nil { if user != nil {
// fetchResult // fetchResult
fetchResult, fetchError = utils.GetMiMcToken(strconv.FormatInt(user.ID, 10)) fetchResult, fetchError = utils.CreateMiMcToken(strconv.FormatInt(user.ID, 10))
if err := json.Unmarshal([]byte(fetchResult), &imTokenDto); err != nil { if err := json.Unmarshal([]byte(fetchResult), &imTokenDto); err != nil {
c.JSON(configs.ResponseFail, "注册失败!", &err) c.JSON(configs.ResponseFail, "注册失败!", &err)
} }
...@@ -126,7 +126,7 @@ func (c *PublicController) Register() { ...@@ -126,7 +126,7 @@ func (c *PublicController) Register() {
if accountID, err := c.UserRepository.Add(user); err == nil { if accountID, err := c.UserRepository.Add(user); err == nil {
fetchResult, fetchError = utils.GetMiMcToken(strconv.FormatInt(accountID, 10)) fetchResult, fetchError = utils.CreateMiMcToken(strconv.FormatInt(accountID, 10))
if err := json.Unmarshal([]byte(fetchResult), &imTokenDto); err != nil { if err := json.Unmarshal([]byte(fetchResult), &imTokenDto); err != nil {
c.JSON(configs.ResponseFail, "注册失败!", &err) c.JSON(configs.ResponseFail, "注册失败!", &err)
} }
...@@ -149,7 +149,7 @@ func (c *PublicController) Register() { ...@@ -149,7 +149,7 @@ func (c *PublicController) Register() {
admin = c.AdminRepository.GetAdmin(auth.UID) admin = c.AdminRepository.GetAdmin(auth.UID)
// fetchResult // fetchResult
fetchResult, fetchError = utils.GetMiMcToken(strconv.FormatInt(admin.ID, 10)) fetchResult, fetchError = utils.CreateMiMcToken(strconv.FormatInt(admin.ID, 10))
// imTokenDto // imTokenDto
if err := json.Unmarshal([]byte(fetchResult), &imTokenDto); err != nil { if err := json.Unmarshal([]byte(fetchResult), &imTokenDto); err != nil {
......
No preview for this file type
package grpcs
import (
context "context"
"crypto/md5"
fmt "fmt"
"log"
"net"
grpc "google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)
// 业务实现方法的容器
type server struct{}
// 为server定义 DoMD5 方法 内部处理请求并返回结果
// 参数 (context.Context[固定], *test.Req[相应接口定义的请求参数])
// 返回 (*test.Res[相应接口定义的返回参数,必须用指针], error)
func (s *server) DoMD5(ctx context.Context, in *Req) (*Res, error) {
fmt.Println("MD5方法请求JSON:" + in.JsonStr)
return &Res{BackJson: "MD5 :" + fmt.Sprintf("%x", md5.Sum([]byte(in.JsonStr)))}, nil
}
// Run run grpc server
func Run() {
lis, err := net.Listen("tcp", ":8028") //监听所有网卡8028端口的TCP连接
if err != nil {
log.Fatalf("监听失败: %v", err)
}
s := grpc.NewServer() //创建gRPC服务
/**注册接口服务
* 以定义proto时的service为单位注册,服务中可以有多个方法
* (proto编译时会为每个service生成Register***Server方法)
* 包.注册服务方法(gRpc服务实例,包含接口方法的结构体[指针])
*/
RegisterWaiterServer(s, &server{})
/**如果有可以注册多个接口服务,结构体要实现对应的接口方法
* user.RegisterLoginServer(s, &server{})
* minMovie.RegisterFbiServer(s, &server{})
*/
// 在gRPC服务器上注册反射服务
reflection.Register(s)
// 将监听交给gRPC服务处理
err = s.Serve(lis)
if err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: test.proto
// 定义包名
package grpcs
import (
context "context"
fmt "fmt"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// 定义 Req 消息结构
type Req struct {
// 类型 字段 = 标识号
JsonStr string `protobuf:"bytes,1,opt,name=jsonStr,proto3" json:"jsonStr,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Req) Reset() { *m = Req{} }
func (m *Req) String() string { return proto.CompactTextString(m) }
func (*Req) ProtoMessage() {}
func (*Req) Descriptor() ([]byte, []int) {
return fileDescriptor_c161fcfdc0c3ff1e, []int{0}
}
func (m *Req) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Req.Unmarshal(m, b)
}
func (m *Req) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Req.Marshal(b, m, deterministic)
}
func (m *Req) XXX_Merge(src proto.Message) {
xxx_messageInfo_Req.Merge(m, src)
}
func (m *Req) XXX_Size() int {
return xxx_messageInfo_Req.Size(m)
}
func (m *Req) XXX_DiscardUnknown() {
xxx_messageInfo_Req.DiscardUnknown(m)
}
var xxx_messageInfo_Req proto.InternalMessageInfo
func (m *Req) GetJsonStr() string {
if m != nil {
return m.JsonStr
}
return ""
}
// 定义 Res 消息结构
type Res struct {
BackJson string `protobuf:"bytes,1,opt,name=backJson,proto3" json:"backJson,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Res) Reset() { *m = Res{} }
func (m *Res) String() string { return proto.CompactTextString(m) }
func (*Res) ProtoMessage() {}
func (*Res) Descriptor() ([]byte, []int) {
return fileDescriptor_c161fcfdc0c3ff1e, []int{1}
}
func (m *Res) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Res.Unmarshal(m, b)
}
func (m *Res) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Res.Marshal(b, m, deterministic)
}
func (m *Res) XXX_Merge(src proto.Message) {
xxx_messageInfo_Res.Merge(m, src)
}
func (m *Res) XXX_Size() int {
return xxx_messageInfo_Res.Size(m)
}
func (m *Res) XXX_DiscardUnknown() {
xxx_messageInfo_Res.DiscardUnknown(m)
}
var xxx_messageInfo_Res proto.InternalMessageInfo
func (m *Res) GetBackJson() string {
if m != nil {
return m.BackJson
}
return ""
}
func init() {
proto.RegisterType((*Req)(nil), "grpcs.Req")
proto.RegisterType((*Res)(nil), "grpcs.Res")
}
func init() {
proto.RegisterFile("test.proto", fileDescriptor_c161fcfdc0c3ff1e)
}
var fileDescriptor_c161fcfdc0c3ff1e = []byte{
// 130 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0x49, 0x2d, 0x2e,
0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x4d, 0x2f, 0x2a, 0x48, 0x2e, 0x56, 0x92, 0xe7,
0x62, 0x0e, 0x4a, 0x2d, 0x14, 0x92, 0xe0, 0x62, 0xcf, 0x2a, 0xce, 0xcf, 0x0b, 0x2e, 0x29, 0x92,
0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x82, 0x71, 0x95, 0x14, 0x41, 0x0a, 0x8a, 0x85, 0xa4, 0xb8,
0x38, 0x92, 0x12, 0x93, 0xb3, 0xbd, 0x8a, 0xf3, 0xf3, 0xa0, 0x2a, 0xe0, 0x7c, 0x23, 0x6d, 0x2e,
0xb6, 0xf0, 0xc4, 0xcc, 0x92, 0xd4, 0x22, 0x21, 0x45, 0x2e, 0x56, 0x97, 0x7c, 0x5f, 0x17, 0x53,
0x21, 0x2e, 0x3d, 0xb0, 0xf1, 0x7a, 0x41, 0xa9, 0x85, 0x52, 0x08, 0x76, 0xb1, 0x12, 0x43, 0x12,
0x1b, 0xd8, 0x7a, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc3, 0x16, 0xa5, 0x68, 0x8c, 0x00,
0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConnInterface
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6
// WaiterClient is the client API for Waiter service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type WaiterClient interface {
// 定义接口 (结构体可以复用)
// 方法 (请求消息结构体) returns (返回消息结构体) {}
DoMD5(ctx context.Context, in *Req, opts ...grpc.CallOption) (*Res, error)
}
type waiterClient struct {
cc grpc.ClientConnInterface
}
func NewWaiterClient(cc grpc.ClientConnInterface) WaiterClient {
return &waiterClient{cc}
}
func (c *waiterClient) DoMD5(ctx context.Context, in *Req, opts ...grpc.CallOption) (*Res, error) {
out := new(Res)
err := c.cc.Invoke(ctx, "/grpcs.Waiter/DoMD5", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// WaiterServer is the server API for Waiter service.
type WaiterServer interface {
// 定义接口 (结构体可以复用)
// 方法 (请求消息结构体) returns (返回消息结构体) {}
DoMD5(context.Context, *Req) (*Res, error)
}
// UnimplementedWaiterServer can be embedded to have forward compatible implementations.
type UnimplementedWaiterServer struct {
}
func (*UnimplementedWaiterServer) DoMD5(ctx context.Context, req *Req) (*Res, error) {
return nil, status.Errorf(codes.Unimplemented, "method DoMD5 not implemented")
}
func RegisterWaiterServer(s *grpc.Server, srv WaiterServer) {
s.RegisterService(&_Waiter_serviceDesc, srv)
}
func _Waiter_DoMD5_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Req)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WaiterServer).DoMD5(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/grpcs.Waiter/DoMD5",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WaiterServer).DoMD5(ctx, req.(*Req))
}
return interceptor(ctx, in, info, handler)
}
var _Waiter_serviceDesc = grpc.ServiceDesc{
ServiceName: "grpcs.Waiter",
HandlerType: (*WaiterServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "DoMD5",
Handler: _Waiter_DoMD5_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "test.proto",
}
syntax = "proto3";
// 定义包名
package grpcs;
// 可以定义多个服务,每个服务内可以定义多个接口
service Waiter {
// 定义接口 (结构体可以复用)
// 方法 (请求消息结构体) returns (返回消息结构体) {}
rpc DoMD5 (Req) returns (Res) {}
}
// 定义 Req 消息结构
message Req {
// 类型 字段 = 标识号
string jsonStr = 1;
}
// 定义 Res 消息结构
message Res {
string backJson = 1;
}
// PSjsonStrbackJson只是随手写的名字,并没有用json
\ No newline at end of file
...@@ -6,11 +6,13 @@ import ( ...@@ -6,11 +6,13 @@ import (
"github.com/Xiaomi-mimc/mimc-go-sdk/util/log" "github.com/Xiaomi-mimc/mimc-go-sdk/util/log"
"github.com/astaxie/beego" "github.com/astaxie/beego"
"github.com/astaxie/beego/logs" "github.com/astaxie/beego/logs"
"github.com/astaxie/beego/toolbox"
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
"kefu_server/controllers" "kefu_server/controllers"
"kefu_server/db" "kefu_server/db"
_ "kefu_server/routers" _ "kefu_server/routers"
"kefu_server/task"
) )
// Initialization log // Initialization log
...@@ -39,7 +41,9 @@ func main() { ...@@ -39,7 +41,9 @@ func main() {
initLog() initLog()
// init task // init task
// task.Run() task.Run()
toolbox.StartTask()
defer toolbox.StopTask()
/// Static file configuration /// Static file configuration
beego.SetStaticPath("/", "public/client") beego.SetStaticPath("/", "public/client")
...@@ -49,10 +53,10 @@ func main() { ...@@ -49,10 +53,10 @@ func main() {
// Handling Error // Handling Error
beego.ErrorController(&controllers.ErrorController{}) beego.ErrorController(&controllers.ErrorController{})
// init robot // grpcserver init
// im.RobotInit() // go grpcs.Run()
// run application // run application
beego.Run() beego.Run()
} }
\ No newline at end of file
...@@ -15,6 +15,7 @@ type AdminRepositoryInterface interface { ...@@ -15,6 +15,7 @@ type AdminRepositoryInterface interface {
Add(admin *models.Admin, col1 string) (bool, int64, error) Add(admin *models.Admin, col1 string) (bool, int64, error)
Delete(id int64) (int64, error) Delete(id int64) (int64, error)
GetAdmins(request *AdminPaginationDto) (*AdminPaginationDto, error) GetAdmins(request *AdminPaginationDto) (*AdminPaginationDto, error)
CheckAdminsLoginTimeOutAndSetOffline(lastMessageUnixTimer int64) int64
} }
// AdminPaginationDto a struct // AdminPaginationDto a struct
...@@ -46,6 +47,15 @@ func GetAdminRepositoryInstance() *AdminRepository { ...@@ -46,6 +47,15 @@ func GetAdminRepositoryInstance() *AdminRepository {
return instance return instance
} }
// CheckAdminsLoginTimeOutAndSetOffline Check if user login timeout
func (r *AdminRepository) CheckAdminsLoginTimeOutAndSetOffline(lastMessageUnixTimer int64) int64 {
count, _ := r.q.Filter("online__in", 1, 2).Filter("last_activity__lte", lastMessageUnixTimer).Update(orm.Params{
"online": 0,
"current_con_user": 0,
})
return count
}
// GetAdmin get one admin with id // GetAdmin get one admin with id
func (r *AdminRepository) GetAdmin(id int64) *models.Admin { func (r *AdminRepository) GetAdmin(id int64) *models.Admin {
var admin models.Admin var admin models.Admin
......
...@@ -18,6 +18,8 @@ type ContactRepositoryInterface interface { ...@@ -18,6 +18,8 @@ type ContactRepositoryInterface interface {
DeleteAll(uid int64) (int64, error) DeleteAll(uid int64) (int64, error)
Add(contact *models.Contact) (int64, error) Add(contact *models.Contact) (int64, error)
GetContactWithIds(ids ...int64) (*models.Contact, error) GetContactWithIds(ids ...int64) (*models.Contact, error)
SetTimeOutContactOffline()
GetTimeOutList() []*models.Contact
} }
// ContactRepository struct // ContactRepository struct
...@@ -32,6 +34,27 @@ func GetContactRepositoryInstance() *ContactRepository { ...@@ -32,6 +34,27 @@ func GetContactRepositoryInstance() *ContactRepository {
return instance return instance
} }
// GetTimeOutList get all timeout List
func (r *ContactRepository) GetTimeOutList(lastMessageUnixTimer int64) []*models.Contact {
var contacts []*models.Contact
_, err := r.o.Raw("SELECT * FROM `contact` WHERE `create_at` <= ? AND `is_session_end` = 0 AND `last_message_type` != 'timeout'", lastMessageUnixTimer).QueryRows(&contacts)
if err != nil {
logs.Warn("GetTimeOutList get all timeout List------------", err)
}
return contacts
}
// SetTimeOutContactOffline set time out user offline
func (r *ContactRepository) SetTimeOutContactOffline(userOffLineUnixTimer int64) {
_, err := r.q.Filter("create_at__lte", userOffLineUnixTimer).Update(orm.Params{
"last_message_type": "timeout",
"is_session_end": 1,
})
if err != nil {
logs.Warn("SetTimeOutContactOffline set time out user offline------------", err)
}
}
// Add add a Contact // Add add a Contact
func (r *ContactRepository) Add(contact *models.Contact) (int64, error) { func (r *ContactRepository) Add(contact *models.Contact) (int64, error) {
row, err := r.o.Insert(contact) row, err := r.o.Insert(contact)
......
...@@ -17,6 +17,7 @@ type UserRepositoryInterface interface { ...@@ -17,6 +17,7 @@ type UserRepositoryInterface interface {
Update(id int64, params *orm.Params) (int64, error) Update(id int64, params *orm.Params) (int64, error)
Delete(id int64) (int64, error) Delete(id int64) (int64, error)
GetOnlineCount() (int64, error) GetOnlineCount() (int64, error)
CheckUsersLoginTimeOutAndSetOffline(lastMessageUnixTimer int64) int64
} }
// UserRepository struct // UserRepository struct
...@@ -31,6 +32,18 @@ func GetUserRepositoryInstance() *UserRepository { ...@@ -31,6 +32,18 @@ func GetUserRepositoryInstance() *UserRepository {
return instance return instance
} }
// CheckUsersLoginTimeOutAndSetOffline Check if user login timeout
func (r *UserRepository) CheckUsersLoginTimeOutAndSetOffline(lastMessageUnixTimer int64) int64 {
count, err := r.q.Filter("online__in", 1, 2).Filter("last_activity__lte", lastMessageUnixTimer).Update(orm.Params{
"online": 0,
"is_window": 0,
})
if err != nil {
logs.Warn("CheckUsersLoginTimeOutAndSetOffline Check if user login timeout------------", err)
}
return count
}
// Add create a user // Add create a user
func (r *UserRepository) Add(user *models.User) (int64, error) { func (r *UserRepository) Add(user *models.User) (int64, error) {
id, err := r.o.Insert(user) id, err := r.o.Insert(user)
......
...@@ -3,117 +3,90 @@ package task ...@@ -3,117 +3,90 @@ package task
import ( import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"kefu_server/robot"
"kefu_server/models" "kefu_server/models"
"kefu_server/services"
"kefu_server/utils" "kefu_server/utils"
"strconv"
"time" "time"
"github.com/astaxie/beego/logs" "github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
"github.com/astaxie/beego/toolbox" "github.com/astaxie/beego/toolbox"
) )
// 定时任务 // Timed task
func appTask() { func appTask() {
o := orm.NewOrm() // Task scheduling (will be executed once every 5 minute)
// 任务调度(1分钟会执行一次) checkOnLineTk := toolbox.NewTask("checkOnLine", "0 */5 * * * *", func() error {
checkOnLineTk := toolbox.NewTask("checkOnLine", "0 */1 * * * *", func() error {
im.RobotInit() // timers
userOffLineUnixTimer := time.Now().Unix() - (60 * 10) // 用户最后活动时间T出在线状态规则 userOffLineUnixTimer := time.Now().Unix() - (60 * 10) // User's last activity time T out online status rule
adminOffLineUnixTimer := time.Now().Unix() - (60 * 30) // 最后回复消息时间清理回话规则 adminOffLineUnixTimer := time.Now().Unix() - (60 * 30) // Final reply time
lastMessageUnixTimer := time.Now().Unix() - (60 * 8) // 判断用户是否超过一定时间不使用,强制其下线 lastMessageUnixTimer := time.Now().Unix() - (60 * 8) // Determine if the user will not use it for a certain period of time and force them to go offline
uqs := o.QueryTable(new(models.User))
aqs := o.QueryTable(new(models.Admin)) // user
// 检查User userOfflineCount := services.GetUserRepositoryInstance().CheckUsersLoginTimeOutAndSetOffline(lastMessageUnixTimer)
count, _ := uqs.Filter("online__in", 1, 2).Filter("last_activity__lte", lastMessageUnixTimer).Update(orm.Params{ logs.Info("清理登录超时user", userOfflineCount, "个被强制下线")
"online": 0,
"is_window": 0,
})
logs.Info("清理登录超时用户,有", count, "个用户被强制下线")
// 检查Admin
_, _ = aqs.Filter("online__in", 1, 2).Filter("last_activity__lte", adminOffLineUnixTimer).Update(orm.Params{
"online": 0,
"current_con_user": 0,
})
// 2.判断用户是否超时无应答
cqs := o.QueryTable(new(models.Contact))
// 检查(有机器人在线)
if len(im.Robots) > 0 {
robot := im.Robots[0]
var contacts []models.Contact
_, _ = o.Raw("SELECT * FROM `contact` WHERE `create_at` <= ? AND `is_session_end` = 0 AND `last_message_type` != 'timeout'", lastMessageUnixTimer).QueryRows(&contacts)
logs.Info("清理会话超时用户,有", len(contacts), "个用户被结束对话")
for _, contact := range contacts {
// 判断发送方是客服就不处理发送了
if err := o.Read(&models.Admin{ID: contact.FromAccount}); err == nil {
continue
}
// 发送超时消息体
message := models.Message{}
message.BizType = "timeout"
message.Read = 0
appAccount, _ := strconv.ParseInt(robot.AppAccount(), 10, 64)
message.FromAccount = appAccount
message.Timestamp = time.Now().Unix()
message.Payload = "由于您长时间未回复,本次会话超时了"
message.ToAccount = contact.FromAccount
var messageJSON []byte
var messageString string
messageJSON, _ = json.Marshal(message)
messageString = base64.StdEncoding.EncodeToString([]byte(messageJSON))
robot.SendMessage(strconv.FormatInt(contact.FromAccount, 10), []byte(messageString))
// 该客户超时后给客服发送提醒消息 // admin
message.FromAccount = contact.FromAccount adminOfflineCount := services.GetAdminRepositoryInstance().CheckAdminsLoginTimeOutAndSetOffline(adminOffLineUnixTimer)
message.ToAccount = contact.ToAccount logs.Info("清理登录超时admin", adminOfflineCount, "个被强制下线")
// get offline all robots
robots, _ := services.GetRobotRepositoryInstance().GetRobotOnlineAll()
if robots != nil && len(robots) == 0 {
services.GetContactRepositoryInstance().SetTimeOutContactOffline(userOffLineUnixTimer)
}
contacts := services.GetContactRepositoryInstance().GetTimeOutList(lastMessageUnixTimer)
logs.Info("清理会话超时用户,有", len(contacts), "个被结束对话")
for _, contact := range contacts {
// Does not handle customer service
if admin := services.GetAdminRepositoryInstance().GetAdmin(contact.FromAccount); admin != nil {
continue
}
robot := robots[0]
// message body
message := models.Message{}
message.BizType = "timeout"
message.Read = 0
message.FromAccount = robot.ID
message.Timestamp = time.Now().Unix()
message.Payload = "由于您长时间未回复,本次会话超时了"
message.ToAccount = contact.FromAccount
var messageJSON []byte
var messageString string
messageJSON, _ = json.Marshal(message)
messageString = base64.StdEncoding.EncodeToString([]byte(messageJSON))
utils.PushMessage(contact.FromAccount, messageString)
// Send a reminder message to customer service
message.FromAccount = contact.FromAccount
message.ToAccount = contact.ToAccount
messageJSON, _ = json.Marshal(message)
messageString = base64.StdEncoding.EncodeToString([]byte(messageJSON))
utils.PushMessage(contact.ToAccount, messageString)
utils.MessageInto(message, true)
// Message after timeout
if robot.TimeoutText != "" {
message.FromAccount = robot.ID
message.ToAccount = contact.FromAccount
message.BizType = "text"
message.Key = time.Now().Unix()
message.Payload = robot.TimeoutText
messageJSON, _ = json.Marshal(message) messageJSON, _ = json.Marshal(message)
messageString = base64.StdEncoding.EncodeToString([]byte(messageJSON)) messageString = base64.StdEncoding.EncodeToString([]byte(messageJSON))
robot.SendMessage(strconv.FormatInt(contact.ToAccount, 10), []byte(messageString)) utils.PushMessage(contact.FromAccount, messageString)
utils.MessageInto(message, true)
// 超时后消息
// 数据库获取机器人配置信息
robotData := models.Robot{ID: appAccount}
cacheRobotKey := "robot_" + string(appAccount)
if robotDataTemp := im.BmCache.Get(cacheRobotKey); robotDataTemp == nil {
robotData = models.Robot{ID: appAccount}
_ = o.Read(&robotData)
robotDataJSON, _ := json.Marshal(robotData)
_ = im.BmCache.Put(cacheRobotKey, robotDataJSON, 60*time.Second)
} else {
_ = json.Unmarshal([]byte(string(robotDataTemp.([]byte))), &robotData)
}
if robotData.TimeoutText != "" {
message.FromAccount = appAccount
message.ToAccount = contact.FromAccount
message.BizType = "text"
message.Key = time.Now().Unix()
message.Payload = robotData.TimeoutText
messageJSON, _ = json.Marshal(message)
messageString = base64.StdEncoding.EncodeToString([]byte(messageJSON))
robot.SendMessage(strconv.FormatInt(contact.FromAccount, 10), []byte(messageString))
}
} }
} else {
// 执行到这里说明,机器人死掉了
logs.Error("执行到这里说明,机器人死掉了")
im.RobotInit()
_, _ = cqs.Filter("create_at__lte", userOffLineUnixTimer).Update(orm.Params{
"last_message_type": "timeout",
"is_session_end": 1,
})
} }
return nil return nil
}) })
toolbox.AddTask("checkOnLine", checkOnLineTk) toolbox.AddTask("checkOnLine", checkOnLineTk)
toolbox.StartTask()
defer toolbox.StopTask()
} }
...@@ -19,8 +19,8 @@ type TokenHandler struct { ...@@ -19,8 +19,8 @@ type TokenHandler struct {
AppAccount string `json:"appAccount"` AppAccount string `json:"appAccount"`
} }
// GetMiMcToken ... // CreateMiMcToken ...
func GetMiMcToken(accountID string) (string, error) { func CreateMiMcToken(accountID string) (string, error) {
tokenHandler := new(TokenHandler) tokenHandler := new(TokenHandler)
tokenHandler.httpURL = beego.AppConfig.String("mimc_HttpUrl") tokenHandler.httpURL = beego.AppConfig.String("mimc_HttpUrl")
tokenHandler.AppID, _ = beego.AppConfig.Int64("mimc_appId") tokenHandler.AppID, _ = beego.AppConfig.Int64("mimc_appId")
......
package utils
import (
"fmt"
"strconv"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
)
// PushMessage send message
// toAccount receive message account
// bizType message type
// msg message base 64
func PushMessage(toAccount int64, msg string) bool {
appID, _ := beego.AppConfig.Int64("mimc_appId")
appKey := beego.AppConfig.String("mimc_appKey")
appSecret := beego.AppConfig.String("mimc_appSecret")
api := "https://mimc.chat.xiaomi.net/api/push/p2p/"
var request = map[string]string{}
request["appId"] = strconv.FormatInt(appID, 10)
request["appKey"] = appKey
request["appSecret"] = appSecret
request["fromAccount"] = "1"
request["toAccount"] = strconv.FormatInt(toAccount, 10)
request["msg"] = msg
response := HTTPRequest(api, "POST", request, "")
logs.Info(response)
if response.Code != 200 {
fmt.Println(response)
return false
}
return true
}
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