// 添加好友关系 func handleUserRelationAdd(resp http.ResponseWriter, req *http.Request) { if req.Method == "POST" { receiver_category_id := req.FormValue("receiver_category_id") buddy_request_id := req.FormValue("buddy_request_id") buddyrequest, _ := model.GetBuddyRequestById(buddy_request_id) if buddyrequest != nil { receiver := buddyrequest.Receiver sender := buddyrequest.Sender sender_category_id := buddyrequest.SenderCategoryId //开启事务 tx, _ := model.Database.Begin() //修改好友请求记录中接受人的好友分组ID _, err := model.UpdateBuddyRequestReceiverCategoryId(tx, buddy_request_id, receiver_category_id) //添加请求人好友关系数据 _, err = model.AddFriendRelation(tx, receiver, sender_category_id) //添加接收人好友关系数据 _, err = model.AddFriendRelation(tx, sender, receiver_category_id) //修改好友请求记录中状态 _, err = model.UpdateBuddyRequestStatus(tx, buddy_request_id, "1") if err != nil { tx.Rollback() resp.Write(common.NewIMResponseSimple(100, err.Error(), "").Encode()) return } else { tx.Commit() //判断请求者是不是在线 在线就把接受者推送给请求者 conn, _ := model.GetConnByUserId(sender) if conn != nil { //在线 user, _ := model.GetUserById(receiver) data := make(map[string]interface{}) data["category_id"] = sender_category_id data["user"] = user ClientMaps[conn.Key].PutOut(common.NewIMResponseData(util.SetData("user", data), common.ADD_BUDDY)) } conn, _ = model.GetConnByUserId(receiver) if conn != nil { user, _ := model.GetUserById(sender) data := make(map[string]interface{}) data["category_id"] = receiver_category_id data["user"] = user ClientMaps[conn.Key].PutOut(common.NewIMResponseData(util.SetData("user", data), common.ADD_BUDDY)) } resp.Write(common.NewIMResponseSimple(0, "好友关系建立成功", "").Encode()) return } } else { resp.Write(common.NewIMResponseSimple(104, "该好友请求不存在", "").Encode()) } } else { resp.Write(common.NewIMResponseSimple(404, "Not Found: "+req.Method, "").Encode()) } }
/* 新客户端请求处理方法 */ func (this *Server) joinHandler(conn net.Conn) { //获取UUID作为客户端的key key := uuid.New() // 创建一个客户端 client := common.CreateClient(key, conn) //给客户端指定key this.clients[key] = client // log.Printf("新客户端Key:[%s] online:%d", client.Key, len(ClientMaps)) // 开启协程不断地接收消息 go func() { for { // 客户端读取消息 msg := <-client.In // 消息交给嗅探器 触发对应的处理方法 this.insniffer <- msg } }() // 开启协程一直等待断开 go func() { for { //客户端接收断开请求 conn := <-client.Quit // log.Printf("客户端:[%s]退出", client.Key) //请求交给嗅探器 触发对应的处理方法 this.quitsniffer <- conn } }() // 返回客户端的唯一标识 data := make(map[string]interface{}) data["key"] = key client.PutOut(common.NewIMResponseData(util.SetData("conn", data), common.GET_KEY_RETURN)) }
/* 客户端退出处理方法 */ func (this *Server) quitHandler(client *common.Client) { if client != nil { // 通知在线的好友,我离线了 if client.Login != nil { // 判断要求改变的状态和当前该用户的状态是否一致 model.DeleteConnByKey(client.Key) count, _ := model.CountConnByUserId(client.Login.UserId) // 如果没有这用户的连接,同时更新用户状态为离线 if count == 0 { model.UpdateUserStatus(client.Login.UserId, "0") } keys, err := model.GetBuddiesKeyById(client.Login.UserId) if err == nil { for i := 0; i < len(keys); i++ { //给对应的连接推送好友状态变化的通知 data := make(map[string]string) data["id"] = client.Login.UserId data["state"] = "0" if this.clients[keys[i]] != nil { this.clients[keys[i]].PutOut(common.NewIMResponseData(util.SetData("user", data), common.PUSH_STATUS_CHANGE)) } } } } // 调用客户端关闭方法 client.Close() delete(this.clients, client.Key) // log.Printf("客户端退出: %s online:%d", client.Key, len(ClientMaps)) } }
/** 查询请求处理方法 */ func handleQuery(resp http.ResponseWriter, req *http.Request) { nick := req.FormValue("nick") users, err := model.QueryUser("nick", "like", nick) if err == nil { resp.Write(common.NewIMResponseData(util.SetData("users", users), "").Encode()) } }
func handleUserCategoryQuery(resp http.ResponseWriter, req *http.Request) { id := req.FormValue("id") categories, err := model.GetCategoriesByUserId(id) if err != nil { resp.Write(common.NewIMResponseSimple(100, err.Error(), "").Encode()) } else { resp.Write(common.NewIMResponseData(util.SetData("categories", categories), "").Encode()) } }
// 系统状态信息 func handleSystem(resp http.ResponseWriter, req *http.Request) { mem, _ := mem.VirtualMemory() cpuNum, _ := cpu.CPUCounts(true) cpuInfo, _ := cpu.CPUPercent(10*time.Microsecond, true) data := make(map[string]interface{}) data["im.conn"] = len(ClientMaps) data["mem.total"] = fmt.Sprintf("%vMB", mem.Total/1024/1024) data["mem.free"] = fmt.Sprintf("%vMB", mem.Free/1024/1024) data["mem.used_percent"] = fmt.Sprintf("%s%%", strconv.FormatFloat(mem.UsedPercent, 'f', 2, 64)) data["cpu.num"] = cpuNum data["cpu.info"] = cpuInfo resp.Write(common.NewIMResponseData(data, "").Encode()) }
// 登录主方法 func login(resp http.ResponseWriter, account string, password string, ip string) { if account == "" { resp.Write(common.NewIMResponseSimple(101, "账号不能为空", "").Encode()) } else if password == "" { resp.Write(common.NewIMResponseSimple(102, "密码不能为空", "").Encode()) } else { num, err := model.CheckAccount(account) if err != nil { resp.Write(common.NewIMResponseSimple(100, err.Error(), "").Encode()) return } if num > 0 { user, err := model.LoginUser(account, password) if err != nil { resp.Write(common.NewIMResponseSimple(100, err.Error(), "").Encode()) return } if !strings.EqualFold(user.Id, "") { token := uuid.New() if _, err := model.SaveLogin(user.Id, token, ip); err != nil { resp.Write(common.NewIMResponseSimple(100, err.Error(), "").Encode()) } else { // returnData := make(map[string]string) // returnData["id"] = user.Id // returnData["nick"] = user.Nick // returnData["avatar"] = user.Avatar // returnData["status"] = user.Status // returnData["token"] = token //token uuid 带 横杠 // returnData["sign"]=user.Sign user.Token = token resp.Write(common.NewIMResponseData(util.SetData("user", user), "LOGIN_RETURN").Encode()) } } else { resp.Write(common.NewIMResponseSimple(104, "密码错误", "").Encode()) } } else { resp.Write(common.NewIMResponseSimple(103, "账号不存在", "").Encode()) } } }
// 添加好友分类 func handleUserCategoryAdd(resp http.ResponseWriter, req *http.Request) { switch req.Method { case "GET": //获取好友列表 userId := req.FormValue("user_id") categories, err := model.GetCategoriesByUserId(userId) if err != nil { resp.Write(common.NewIMResponseSimple(100, err.Error(), "").Encode()) return } categories, err = model.GetBuddiesByCategories(categories) if err != nil { resp.Write(common.NewIMResponseSimple(100, err.Error(), "").Encode()) return } resp.Write(common.NewIMResponseData(util.SetData("categories", categories), "").Encode()) case "POST": // 添加好友列表 userId := req.FormValue("user_id") name := req.FormValue("name") if userId == "" { resp.Write(common.NewIMResponseSimple(101, "用户ID不能为空", "").Encode()) } else if name == "" { resp.Write(common.NewIMResponseSimple(102, "类别名称不能为空", "").Encode()) } else { _, err := model.AddCategory(userId, name) if err != nil { resp.Write(common.NewIMResponseSimple(103, err.Error(), "").Encode()) } else { resp.Write(common.NewIMResponseSimple(0, "添加分类成功", "").Encode()) } } default: resp.Write(common.NewIMResponseSimple(404, "Not Found: "+req.Method, "").Encode()) } }
func handleUserRelationPush(resp http.ResponseWriter, req *http.Request) { if req.Method == "POST" { sender_category_id := req.FormValue("sender_category_id") sender := req.FormValue("sender") receiver := req.FormValue("receiver") if sender_category_id == "" { resp.Write(common.NewIMResponseSimple(101, "请选择分组", "").Encode()) } else if sender == "" { resp.Write(common.NewIMResponseSimple(102, "请重新登录", "").Encode()) } else { //判断接收人是不是在线 在线直接推送,不在线记录至请求表中 conn, _ := model.GetConnByUserId(receiver) user, _ := model.GetUserById(sender) buddyRequestId, err := model.AddBuddyRequest(sender, sender_category_id, receiver) if err != nil { resp.Write(common.NewIMResponseSimple(100, err.Error(), "").Encode()) } else { if conn != nil { //在线 直接推送 不在线 客户登录时候会激活请求通知 data := make(map[string]interface{}) data["id"] = user.Id data["nick"] = user.Nick data["status"] = user.Status data["sign"] = user.Sign data["avatar"] = user.Avatar data["buddyRequestId"] = buddyRequestId ClientMaps[conn.Key].PutOut(common.NewIMResponseData(util.SetData("user", data), common.PUSH_BUDDY_REQUEST)) resp.Write(common.NewIMResponseSimple(0, "发送好友请求成功", "").Encode()) } resp.Write(common.NewIMResponseSimple(1, "发送好友请求成功", "").Encode()) return } } } else { resp.Write(common.NewIMResponseSimple(404, "Not Found: "+req.Method, "").Encode()) } }
/* 接收消息处理方法 */ func (this *Server) receivedHandler(request common.IMRequest) { // log.Println("开始读取数据") // log.Println("读取的数据为", request) // 获取请求的客户端 client := request.Client // 获取请求数据 reqData := request.Data // log.Printf("客户端:[%s]发送命令:[%s]消息内容:[%s]", client.Key, request.Command, request.Data) // 未登录业务处理部分 switch request.Command { case common.GET_CONN: token := reqData["user"]["token"] if token == "" { client.PutOut(common.NewIMResponseSimple(301, "用户令牌不能为空!", common.GET_CONN_RETURN)) return } // 校验用户是否登录,把Login数据放在client当中 login, err := model.GetLoginByToken(token) if err != nil { client.PutOut(common.NewIMResponseSimple(300, err.Error(), common.GET_CONN_RETURN)) return } client.Login = login // log.Printf("登录比较:token=%s Login=%s", token, client.Login) if !strings.EqualFold(client.Login.Token, token) { client.PutOut(common.NewIMResponseSimple(302, "该用户令牌无效!", common.GET_CONN_RETURN)) return } if client.Login.Id != "" { // 更新在线状态,如果现在已经是在线,然后再设置在线,影响行还是为0 _, err := model.UpdateUserStatus(client.Login.UserId, "1") if err != nil { client.PutOut(common.NewIMResponseSimple(304, "设置用户状态失败!", common.GET_CONN_RETURN)) return } // 创建或者更新连接信息 这个error不能handler,当没有数据时会为 sql: no rows in result set conn, _ := model.GetConnByToken(token) if conn != nil { _, err := model.UpdateConnByToken(client.Key, client.Login.UserId, token) if err != nil { client.PutOut(common.NewIMResponseSimple(300, err.Error(), common.GET_CONN_RETURN)) return } } else { _, err := model.AddConn(client.Key, client.Login.UserId, token) if err != nil { client.PutOut(common.NewIMResponseSimple(300, err.Error(), common.GET_CONN_RETURN)) return } } data := make(map[string]interface{}) data["status"] = 1 client.PutOut(common.NewIMResponseData(util.SetData("conn", data), common.GET_CONN_RETURN)) // 通知在线的好友,我上线了 keys, err := model.GetBuddiesKeyById(client.Login.UserId) if err != nil { client.PutOut(common.NewIMResponseSimple(300, err.Error(), common.SEND_STATUS_CHANGE)) return } for i := 0; i < len(keys); i++ { //给对应的连接推送好友状态变化的通知 data := make(map[string]string) data["id"] = client.Login.UserId data["state"] = "1" if this.clients[keys[i]] != nil { this.clients[keys[i]].PutOut(common.NewIMResponseData(util.SetData("user", data), common.PUSH_STATUS_CHANGE)) } } return } else { client.PutOut(common.NewIMResponseSimple(303, "用户未登录!", common.GET_CONN_RETURN)) return } } // 校验连接是已经授权 if client.Login == nil { client.PutOut(common.NewIMResponseSimple(401, "用户未登录!", common.UNAUTHORIZED)) return } // 已经登录业务逻辑部分 switch request.Command { case common.GET_BUDDY_LIST: // 获取好友分组列表 categories, err := model.GetCategoriesByUserId(client.Login.UserId) if err != nil { client.PutOut(common.NewIMResponseSimple(301, "获取好友分类错误!", common.GET_BUDDY_LIST_RETURN)) return } categories, err = model.GetBuddiesByCategories(categories) if err != nil { client.PutOut(common.NewIMResponseSimple(300, err.Error(), common.GET_BUDDY_LIST_RETURN)) return } client.PutOut(common.NewIMResponseData(util.SetData("categories", categories), common.GET_BUDDY_LIST_RETURN)) //初始化好友列表之后 检查该用户有没有未读的好友请求 并推送给用户 buddyRequests, err := model.GetBuddyRequestsByReceiver(client.Login.UserId) if err != nil { client.PutOut(common.NewIMResponseSimple(300, err.Error(), common.GET_BUDDY_LIST_RETURN)) } if len(buddyRequests) > 0 { for _, buddyRequest := range buddyRequests { user, _ := model.GetUserById(buddyRequest.Sender) data := make(map[string]interface{}) data["id"] = user.Id data["nick"] = user.Nick data["status"] = user.Status data["sign"] = user.Sign data["avatar"] = user.Avatar data["buddyRequestId"] = buddyRequest.Id client.PutOut(common.NewIMResponseData(util.SetData("user", data), common.PUSH_BUDDY_REQUEST)) } } case common.CREATE_SESSION: // 创建会话 //{"command":"CREATE_SESSION","data":{"session":{"sender":"xxx","receiver":"xxx","token":"xxxx"}}} sender := reqData["session"]["sender"] receiver := reqData["session"]["receiver"] if sender == "" { client.PutOut(common.NewIMResponseSimple(301, "发送者不能为空!", common.CREATE_SESSION_RETURN)) return } if receiver == "" { client.PutOut(common.NewIMResponseSimple(302, "接收者不能为空!", common.CREATE_SESSION_RETURN)) return } conversationId := model.GetSession(sender, receiver).Id if conversationId == "" { conversationId = model.AddSession(sender, receiver) } if conversationId == "" { client.PutOut(common.NewIMResponseSimple(303, "创建会话失败", common.GET_CONN_RETURN)) return } else { data := make(map[string]string) data["ticket"] = conversationId data["receiver"] = receiver client.PutOut(common.NewIMResponseData(util.SetData("session", data), common.CREATE_SESSION_RETURN)) } case common.SEND_MSG: ticket := reqData["message"]["ticket"] content := reqData["message"]["content"] if ticket == "" { client.PutOut(common.NewIMResponseSimple(301, "Ticket不能为空!", common.SEND_MSG_RETURN)) return } if content == "" { client.PutOut(common.NewIMResponseSimple(302, "消息内容不能为空!", common.SEND_MSG_RETURN)) return } conversion, err := model.GetSessionById(ticket) if err != nil { client.PutOut(common.NewIMResponseSimple(300, err.Error(), common.SEND_MSG_RETURN)) return } if conversion.Id != "" { isSent := false keys, err := model.GetReceiverKeyByTicket(ticket) if err != nil { client.PutOut(common.NewIMResponseSimple(300, err.Error(), common.SEND_MSG_RETURN)) return } for _, key := range keys { if this.clients[key] == nil { // client.PutOut(common.NewIMResponseSimple(402, "对方还未登录!", common.SEND_MSG_RETURN)) continue } // 把消息转发给接收者 data := make(map[string]string) data["sender"] = client.Login.UserId data["ticket"] = ticket data["content"] = content log.Println("开始转发给:", key) this.clients[key].PutOut(common.NewIMResponseData(util.SetData("message", data), common.PUSH_MSG)) isSent = true } if !isSent { client.PutOut(common.NewIMResponseSimple(304, "对方不在线!", common.GET_CONN_RETURN)) return } } else { client.PutOut(common.NewIMResponseSimple(303, "会话已关闭!", common.SEND_MSG_RETURN)) return } case common.SEND_STATUS_CHANGE: status := reqData["user"]["status"] if status == "" { client.PutOut(common.NewIMResponseSimple(301, "状态不能为空!", common.SEND_STATUS_CHANGE)) return } user, err := model.GetUserByToken(client.Login.Token) if err != nil { client.PutOut(common.NewIMResponseSimple(300, err.Error(), common.SEND_STATUS_CHANGE)) return } //判断用户的合法性 if user.Id == "" { //判断要求改变的状态和当前该用户的状态是否一致 if strings.EqualFold(user.Status, status) { //FIXME 此处不做如果状态是离线就删除用户连接的操作,状态改变认为是客户端手动操作或者网络异常 _, err := model.UpdateUserStatus(user.Id, status) if err != nil { client.PutOut(common.NewIMResponseSimple(304, err.Error(), common.SEND_STATUS_CHANGE)) return } keys, err := model.GetBuddiesKeyById(user.Id) if err != nil { client.PutOut(common.NewIMResponseSimple(300, err.Error(), common.SEND_STATUS_CHANGE)) return } for i := 0; i < len(keys); i++ { //给对应的连接推送好友状态变化的通知 data := make(map[string]string) data["id"] = user.Id data["state"] = reqData["user"]["status"] this.clients[keys[i]].PutOut(common.NewIMResponseData(util.SetData("user", data), common.PUSH_STATUS_CHANGE)) } } else { client.PutOut(common.NewIMResponseSimple(303, "请退出重新登录!", common.SEND_STATUS_CHANGE)) return } } else { client.PutOut(common.NewIMResponseSimple(302, "Token不合法!", common.SEND_STATUS_CHANGE)) return } case common.LOGOUT_REQUEST: client.Quiting() case common.SEND_BUDDY_REQUEST: receiver := reqData["buddyRequest"]["receiver"] //判断接收者是不是在线 user, _ := model.GetUserById(receiver) if user == nil || user.Status == "0" { //不在线 记录到好友请求表中 id, _ := model.AddBuddyRequest(reqData["buddyRequest"]["sender"], reqData["buddyRequest"]["senderCateId"], receiver) if id != nil { } } else { //在线直接推送给接收者 conn, _ := model.GetConnByUserId(receiver) data := make(map[string]string) data["sender"] = reqData["buddyRequest"]["sender"] data["senderCateId"] = reqData["buddyRequest"]["senderCateId"] data["receiver"] = reqData["buddyRequest"]["receiver"] this.clients[conn.Key].PutOut(common.NewIMResponseData(util.SetData("buddyRequest", data), common.PUSH_BUDDY_REQUEST)) } } }