public function actionIndex()
 {
     $conversationId = $this->getQuery('conversationId');
     if (empty($conversationId)) {
         throw new BadRequestHttpException("Missing conversationId");
     }
     $query = ChatMessage::find();
     if ($orderBy = $this->getQuery('orderBy', 'createdAt')) {
         if (StringUtil::isJson($orderBy)) {
             $orderBy = Json::decode($orderBy, true);
             foreach ($orderBy as $key => $value) {
                 if ($value === 'asc' || $value === 'ASC') {
                     $orderBy[$key] = SORT_ASC;
                 } else {
                     $orderBy[$key] = SORT_DESC;
                 }
             }
         } else {
             $orderBy = [$orderBy => SORT_DESC];
         }
         $query->orderBy($orderBy);
     }
     $query->where(['isDeleted' => false, 'conversationId' => new \MongoId($this->getQuery('conversationId'))]);
     return new ActiveDataProvider(['query' => $query]);
 }
 public function actionIndex()
 {
     $deskId = $this->getQuery('deskId');
     $clientOpenId = $this->getQuery('clientOpenId');
     $sentTime = $this->getQuery('sentTime');
     $page = $this->getQuery('page', 1);
     $perPage = $this->getQuery('per-page', 10);
     $start = ($page - 1) * $perPage;
     if (empty($clientOpenId) || empty($deskId) || !isset($sentTime)) {
         throw new BadRequestHttpException('Missing required fields');
     }
     $accountId = $this->getAccountId();
     $conversations = ChatConversation::getByClient($clientOpenId, $accountId, new \MongoId($deskId));
     $conversationIds = ChatConversation::getIdList($conversations);
     $chatMessages = ChatMessage::getByConversations($conversationIds, $perPage, $start, $sentTime);
     $messages = [];
     foreach ($chatMessages as $chatMessage) {
         $messages[] = ['conversationId' => $chatMessage['conversationId'] . '', 'messageId' => $chatMessage->_id . '', 'content' => $chatMessage['content'], 'isReply' => $chatMessage['isReply'], 'sentTime' => $chatMessage['sentTime']];
     }
     return $messages;
 }
 public function actionStatistics()
 {
     $startTime = $this->getQuery('startTime');
     $endTime = $this->getQuery('endTime');
     $accountId = $this->getAccountId();
     $condition = ['accountId' => $accountId, 'isDeleted' => BaseModel::NOT_DELETED];
     if (!empty($startTime) && !empty($endTime)) {
         $condition['createdAt'] = ['$gt' => new \MongoDate(TimeUtil::ms2sTime($startTime)), '$lt' => new \MongoDate(TimeUtil::ms2sTime($endTime))];
     }
     //get the original statistics from db.(raw data)
     $clientCount = ChatConversation::getClientCount($condition);
     $conversationCount = ChatConversation::count($condition);
     $clientMessageCount = ChatMessage::countClientMessage($condition);
     $conversationDailyStatistics = ChatConversation::getDailyData($condition);
     $messageDailyStatistics = ChatMessage::getDailyData($condition);
     //format the statistics for chart
     $categories = [];
     $messageCountSeries = [];
     $clientCountSeries = [];
     $conversationCountSeries = [];
     foreach ($conversationDailyStatistics as $conversationDay) {
         foreach ($messageDailyStatistics as $messageDay) {
             if ($conversationDay['date'] == $messageDay['date']) {
                 $conversationDay['messageCount'] = $messageDay['messageCount'];
             }
         }
         if (empty($conversationDay['messageCount'])) {
             $conversationDay['messageCount'] = 0;
         }
         $categories[] = $conversationDay['date'];
         $messageCountSeries[] = $conversationDay['messageCount'];
         $clientCountSeries[] = $conversationDay['clientCount'];
         $conversationCountSeries[] = $conversationDay['conversationCount'];
     }
     $statistics = ['categories' => $categories, 'series' => [['name' => 'helpdesk_users_count', 'data' => $clientCountSeries], ['name' => 'helpdesk_sessions_count', 'data' => $conversationCountSeries], ['name' => 'helpdesk_sent_message_count', 'data' => $messageCountSeries]]];
     return ['clientCount' => $clientCount, 'conversationCount' => $conversationCount, 'clientMessageCount' => $clientMessageCount, 'statistics' => $statistics];
 }
 /**
  * Get message history
  *
  * <b>Request Type: </b>GET<br/>
  * <b>Request Endpoint: </b>http://{server-domain}/api/chat/conversation/message-history/{id}
  * <b>Summary: </b> This api is for get message history.<br/>
  *
  * <b>Request Parameters: </b><br/>
  *     accesstoken: string<br/>
  *     per-page: int<br/>
  *     page: int<br/>
  *     start: int<br/>
  *     deskId: string, id of the desk.<br/>
  *     clientOpenId: string, the openId of the client.<br/>
  *
  * <b>Response Example: </b><br/>
  *  [
  *      {
  *          "conversationId": "54f401fbe9c2fbe2388b4567",
  *          "content": {
  *              "msgType": "TEXT",
  *              "body": "dfgd"
  *          },
  *          "isReply": false,
  *          "sentTime": 1425277474000
  *      },
  *      {
  *          "conversationId": "54f401fbe9c2fbe2388b4567",
  *          "content": {
  *              "msgType": "TEXT",
  *              "body": "nbbnbnn"
  *          },
  *          "isReply": true,
  *          "sentTime": 1425277469000
  *      },
  *      {
  *          "conversationId": "54f401fbe9c2fbe2388b4567",
  *          "content": {
  *              "msgType": "TEXT",
  *              "body": "asdasd"
  *          },
  *          "isReply": true,
  *          "sentTime": 1425277464000
  *      }
  *  ]
  */
 public function actionMessageHistory()
 {
     $deskId = $this->getQuery('deskId');
     $clientOpenId = $this->getQuery('clientOpenId');
     $page = $this->getQuery('page', 1);
     $perPage = $this->getQuery('per-page', 10);
     $start = $this->getQuery('start', 0);
     $start = empty($start) ? ($page - 1) * $perPage : $start;
     $end = $start + $perPage;
     if (empty($clientOpenId)) {
         throw new BadRequestHttpException('Missing required fields');
     }
     $accountId = $this->getAccountId();
     if (!empty($deskId)) {
         $deskId = new \MongoId($deskId);
     }
     $conversations = ChatConversation::getByClient($clientOpenId, $accountId, $deskId);
     $conversationIds = ChatConversation::getIdList($conversations);
     $chatMessages = ChatMessage::getByConversations($conversationIds, $perPage, $start);
     $messages = [];
     foreach ($chatMessages as $chatMessage) {
         $messages[] = ['conversationId' => (string) $chatMessage['conversationId'], 'content' => $chatMessage['content'], 'isReply' => $chatMessage['isReply'], 'sentTime' => $chatMessage['sentTime']];
     }
     return $messages;
 }
 public function perform()
 {
     $args = $this->args;
     $message = $args['message'];
     $type = $message['msgType'];
     $content = $message['content'];
     $WEConnectAccountInfo = $args['account'];
     $WEConnectUserInfo = $args['user'];
     $accountId = new \MongoId($args['accountId']);
     $accountInfoType = null;
     $source = null;
     switch ($WEConnectAccountInfo['channel']) {
         case 'WEIBO':
             $source = ChatConversation::TYPE_WEIBO;
             $accountInfoType = 'WEIBO';
             break;
         case 'ALIPAY':
             $source = ChatConversation::TYPE_ALIPAY;
             $accountInfoType = 'ALIPAY';
             break;
         case 'WEIXIN':
             $source = ChatConversation::TYPE_WECHAT;
             $accountInfoType = $WEConnectAccountInfo['accountType'];
             break;
         default:
             throw new BadRequestHttpException("Unsupported channel type");
             break;
     }
     $client = ['nick' => $WEConnectUserInfo['nickname'], 'avatar' => $WEConnectUserInfo['headerImgUrl'], 'openId' => $WEConnectUserInfo['id'], 'originId' => $WEConnectUserInfo['originId'], 'source' => $source, 'sourceChannel' => $WEConnectUserInfo['accountId'], 'accountId' => $accountId, 'accountInfo' => ['type' => $accountInfoType, 'name' => $WEConnectAccountInfo['name']]];
     ResqueUtil::log(['message' => 'get message from wechat', 'WEConnectAccountInfo' => $WEConnectAccountInfo, 'WEConnectUserInfo' => $WEConnectUserInfo, 'accountId' => $accountId]);
     if (empty($type) || empty($content)) {
         ResqueUtil::log(['message' => 'missing required fields', 'senario' => 'accepting messages from WeConnect', 'WEConnectAccountInfo' => $WEConnectAccountInfo, 'WEConnectUserInfo' => $WEConnectUserInfo]);
         HelpDesk::sendSystemReplyByType($client, $accountId, HelpDeskSetting::REPLY_ERROR);
         return;
     }
     try {
         if ('EVENT' === $type) {
             switch ($content) {
                 case 'CONNECT':
                     $isInWorkingHour = HelpDeskSetting::isInWorkingHours($accountId);
                     if ($isInWorkingHour) {
                         if (empty($WEConnectAccountInfo)) {
                             ResqueUtil::log(['message' => 'Account parameters missing', 'senario' => 'Wechat message, event connect']);
                             HelpDesk::sendSystemReplyByType($client, $accountId, HelpDeskSetting::REPLY_ERROR);
                             return;
                         }
                         //check if the wechat enduser has connected to a helpdesk
                         $conversation = ChatConversation::findOpenByClientId($WEConnectUserInfo['id'], $accountId);
                         if (!empty($conversation)) {
                             ResqueUtil::log(['message' => 'Have connect to helpdesk already', 'senario' => 'Wechat message, event connect', 'user' => $WEConnectUserInfo, 'accountId' => $accountId]);
                             HelpDesk::sendSystemReplyByType($client, $accountId, HelpDeskSetting::REPLY_CUSTOM, ChatConversation::NO_DUPLICATE_CLIENT);
                             return;
                         }
                         return HelpDesk::connect($client, $accountId);
                     } else {
                         //send the disconnect event to WeConnect
                         Yii::$app->weConnect->sendCustomerServiceMessage($WEConnectUserInfo['id'], $WEConnectUserInfo['accountId'], ['msgType' => ChatConversation::WECHAT_MESSAGE_TYPE_EVENT, 'content' => 'DISCONNECT']);
                         HelpDesk::sendSystemReplyByType($client, $accountId, HelpDeskSetting::REPLY_NONWORKING);
                     }
                     break;
                 case 'DISCONNECT':
                     //get the conversationId
                     $conversation = ChatConversation::findOpenByClientId($WEConnectUserInfo['id'], $accountId, ['type' => 'left']);
                     if (empty($conversation)) {
                         return ['status' => 'ok'];
                     }
                     //disconnect
                     return HelpDesk::disconnect($conversation->_id, ['type' => 'brake']);
                     break;
                 default:
                     throw new BadRequestHttpException("Unsupported event content type");
                     break;
             }
         } else {
             //get the conversation information
             $conversation = ChatConversation::findOpenByClientId($WEConnectUserInfo['id'], $accountId);
             if (empty($conversation)) {
                 $pendingClient = PendingClient::findOne(['openId' => $WEConnectUserInfo['id'], 'accountId' => $accountId]);
                 if (!empty($pendingClient)) {
                     HelpDesk::sendSystemReplyByType($client, $accountId, HelpDeskSetting::REPLY_WAITTING);
                     return ['status' => 'ok'];
                 } else {
                     return HelpDesk::connect($client, $accountId);
                 }
             }
             $desk = $conversation->desk;
             $desk['id'] = (string) $desk['id'];
             $client = $conversation->client;
             $sentTime = TimeUtil::msTime();
             //trigger send message event
             $name = ChatConversation::EVENT_CHAT_MESSAGE;
             $data = ['conversationId' => (string) $conversation->_id, 'desk' => $desk, 'client' => $client, 'chatMessage' => ['content' => ['msgType' => $type, 'body' => $content], 'sentTime' => $sentTime], 'isReply' => false];
             //add chatMessage record
             $chatMessage = ChatMessage::saveRecord(['msgType' => $type, 'body' => $content], $sentTime, false, $conversation->_id, $accountId);
             //helpDesk web client message
             $channels = [ChatConversation::getChannelName($desk['id'], $client['openId'])];
             $data['messageId'] = (string) $chatMessage->_id;
             Yii::$app->tuisongbao->triggerEvent($name, $data, $channels);
             //helpDesk mobile client message
             $pushExtra = ['messageId' => (string) $chatMessage->_id, 'openId' => $client['openId'], 'conversationId' => (string) $conversation->_id, 'sentTime' => $chatMessage->sentTime];
             $pushMessage = empty($client['nick']) ? $content : $client['nick'] . ':' . $content;
             ChatConversation::pushMessage($desk['id'], ChatConversation::EVENT_CHAT_MESSAGE, $pushExtra, $pushMessage);
             return ['status' => 'ok'];
         }
     } catch (Exception $e) {
         LogUtil::error(['message' => $e->getMessage()], 'helpdesk');
         return HelpDesk::sendSystemReplyByType($client, $account, HelpDeskSetting::REPLY_ERROR);
     }
 }
 public static function saveRecord($content, $sentTime, $isReply, $conversationId, $accountId)
 {
     $chatMessage = new ChatMessage();
     $chatMessage->content = $content;
     $chatMessage->sentTime = $sentTime;
     $chatMessage->isReply = $isReply;
     $chatMessage->conversationId = $conversationId;
     $chatMessage->accountId = $accountId;
     if (!$chatMessage->save()) {
         LogUtil::error(['message' => 'save chatMessage failed', 'error' => $chatMessage->errors], 'helpdesk');
         throw new ServerErrorHttpException('save chatConversation failed');
     }
     //update the lastChatTime for chatConversation
     ChatConversation::setLastChatTime($sentTime, $conversationId);
     return $chatMessage;
 }