zentaopms/extension/xuan/im/control.php
2023-05-16 10:50:42 +08:00

3367 lines
129 KiB
PHP

<?php
class im extends control
{
/**
* Server start.
*
* @access public
* @return void
*/
public function sysServerStart()
{
$this->im->setXxdStartTime();
$this->im->userResetStatus();
$this->im->userReindexPinyin();
$this->im->chatInitSystemChat();
$this->im->conferenceResetStatus();
$this->im->updateLastPoll();
$output = new stdClass();
$output->result = 'success';
$output->version = $this->config->version;
if(isset($this->config->fileEncryptionKey) && commonModel::isLicensedMethod('im', 'fileEncrypt')) $output->fileKey = $this->config->fileEncryptionKey;
return $this->app->output($this->app->encrypt($output));
}
/**
* Get serverInfo api.
*
* @param string $account
* @param string $password
* @param string $apiVersion
* @param int $userID
* @param string $version
* @param string $device
* @access public
* @return void
*/
public function sysGetServerInfo($account, $password, $apiVersion = '', $userID = 0, $version = '', $device = 'desktop')
{
$this->app->loadLang('user');
if($this->loadModel('restriction') !== false)
{
$IPRestriction = $this->restriction->getConfiguration();
if(isset($IPRestriction->enabled) && $IPRestriction->enabled == 'open')
{
if(!$this->im->checkIPInCIDRs(helper::getRemoteIp(), $IPRestriction->cidrs))
{
$output = new stdClass();
$output->result = 'fail';
$output->data = 'Illegal Request.';
$output->message = $this->lang->im->IPInvalid;
return $this->app->output($this->app->encrypt($output));
}
}
}
if($device == 'mobile' && isset($this->config->xuanxuan->mobileClient) && $this->config->xuanxuan->mobileClient == 'off')
{
$output = new stdclass();
$output->result = 'fail';
$output->data = 'Illegal Request.';
$output->message = $this->lang->im->mobileLimited;
return $this->app->output($this->app->encrypt($output));
}
$this->app->input['device'] = $device; // set device into input for further uses.
$user = $this->im->userIdentify($account, $password);
if(!is_array($user) || $user->account != $account) $this->im->userAddAction($account, 'loginXuanxuan', 'fail');
if(!$user || (is_object($user) && $user->account != $account))
{
$output = new stdclass();
$output->result = 'fail';
$output->data = 'Illegal Request.';
$output->message = $this->lang->user->loginFailed;
return $this->app->output($this->app->encrypt($output));
}
if(is_string($user) && in_array($user, array('locked', 'banned')))
{
$output = new stdclass();
$output->result = 'fail';
$output->data = $user;
return $this->app->output($this->app->encrypt($output));
}
if($user == 'invalid_token')
{
$output = new stdclass();
$output->result = 'fail';
$output->data = 'Invalid Token.';
$output->message = $this->lang->user->tokenInvalid;
return $this->app->output($this->app->encrypt($output));
}
if (isset($user->cidrs)) {
if(!$this->im->checkIPInCIDRs(helper::getRemoteIp(), $user->cidrs))
{
$output = new stdClass();
$output->result = 'fail';
$output->data = 'Illegal Request.';
$output->message = $this->lang->im->IPInvalid;
return $this->app->output($this->app->encrypt($output));
}
}
$upgradeInfo = $this->loadModel('client')->getUpgrade($version);
if((empty($upgradeInfo) || $upgradeInfo->strategy == 'optional') && version_compare($version, $this->config->minClientVerson, '<'))
{
$output = new stdClass();
$output->result = 'fail';
$output->data = 'Illegal Request.';
$output->message = sprintf($this->lang->im->errorClientVersionNotSupport, $version);
return $this->app->output($this->app->encrypt($output));
}
$outputData = new stdclass();
$outputData->clientUpdate = empty($upgradeInfo) ? null : $upgradeInfo;
$outputData->backend = $this->config->xuanxuan->backend;
$outputData->permissions = extCommonModel::getLicensePropertyValue('permissions');
$outputData->backendURL = $this->im->getServer() . $this->config->webRoot;
$outputData->dismissedGroupLife = isset($this->config->dismissedGroupLife) ? $this->config->dismissedGroupLife : 90; // Unit: Day
$outputData->requestType = $this->config->requestType;
$outputData->requestFix = $this->config->requestFix;
/* Send ice servers configuration. */
if(isset($this->config->xuanxuan->iceServers)) $outputData->iceServers = $this->config->xuanxuan->iceServers;
/* Send owt configuration if available. */
$conferenceConfig = $this->loadModel('conference')->getConfiguration('client');
if(!empty($conferenceConfig))
{
$outputData->conference = $conferenceConfig;
if(isset($this->config->xuanxuan->enableSystemConference))
{
$outputData->conference->enableSystem = (int)$this->config->xuanxuan->enableSystemConference;
} else
{
$outputData->conference->enableSystem = 1;
}
}
if(version_compare($version, '4.7', '<=') && $conferenceConfig->backend == 'owt') $outputData->owt = $conferenceConfig; // Send conference config as `owt` to be compatible with old clients.
/* Pushing related information for mobile devices.*/
/* Send api scheme if client api version mismatch server api version. */
$currentApiVersion = $this->config->maps['$version'];
if($currentApiVersion != $apiVersion) $outputData->apiScheme = $this->im->getApiScheme();
/* Send server local timestamp to client. */
$outputData->serverTime = (double)(microtime(true) * 1000);
/* Include generated token if there is one. (user was logon using password) */
if(isset($user->token)) $outputData->authToken = $user->token;
$outputData->authTokenLifetime = (int)zget($this->config->xuanxuan, 'tokenLifetime', 30);
$outputData->authTokenAuthWindow = (int)zget($this->config->xuanxuan, 'tokenAuthWindow', 20);
if(isset($user->tokenNeedRenew)) $outputData->tokenNeedRenew = $user->tokenNeedRenew;
/* Integration related stuff. */
if(isset($this->config->integration))
{
$integratedFeatures = array();
if(zget($this->config->integration->office, 'officeEnabled')) $integratedFeatures[] = 'collaboraOffice';
$outputData->integration = $integratedFeatures;
}
$output = new stdclass();
$output->result = 'success';
$output->users = array($user->id);
$output->userID = $user->id;
$output->method = 'sysgetserverinfo';
$output->device = $device;
$output->lang = zget($this->app->input, 'lang');
$output->rid = zget($this->app->input, 'rid');
$output->version = $this->config->version;
$output->data = $outputData;
return $this->app->output($this->app->encrypt($output));
}
/**
* Get depts dept and roles list
*
* @param int $userID
* @access public
* @return void
*/
public function sysGetDepts($userID)
{
$this->app->loadLang('user');
$allDepts = $this->loadModel('dept')->getListByType('dept');
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Get depts fail'), 'messageResponsePack');
$depts = array();
foreach($allDepts as $id => $dept)
{
$depts[$id] = array('name' => $dept->name, 'order' => (int)$dept->order, 'parent' => (int)$dept->parent);
}
$data = new stdclass();
$data->depts = $depts;
$data->roles = $this->lang->user->roleList;
unset($data->roles['']);
$output = new stdclass();
$output->result = 'success';
$output->users = array($userID);
$output->data = $data;
return $this->im->sendOutput($output, 'sysgetdeptsResponse');
}
/**
* Login.
*
* @param string $account user account
* @param string $password encrypted password
* @param object $options { simple: 0 | 1, status: 'online' | 'busy' | 'away'}
* @param int $userID
* @param string $version
* @param string $device desktop | mobile
* @access public
* @return void
*/
public function userLogin($account = '', $password = '', $options = array(), $userID = 0, $version = '', $device = 'desktop')
{
$this->app->loadLang('user');
if($this->loadModel('restriction') !== false)
{
$IPRestriction = $this->restriction->getConfiguration();
if(isset($IPRestriction->enabled) && $IPRestriction->enabled == 'open' && !$this->im->checkIPInCIDRs(helper::getRemoteIp(), $IPRestriction->cidrs))
{
return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->IPInvalid, 'messageResponsePack'));
}
}
$this->app->input['device'] = $device; // set device into input for further uses.
$user = $this->im->userIdentify($account, $password);
$lang = $this->app->input['lang'];
$simple = $options && isset($options->simple) && $options->simple;
$status = $options && isset($options->status) ? $options->status : 'online';
if(!$user) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->user->loginFailed), 'messageResponsePack');
$comment = json_encode(array('version' => 'xuanxuan-v' . (empty($version) ? '?' : $version)));
if(is_string($user) && in_array($user, array('locked', 'banned', 'invalid_token')))
{
$this->im->userAddAction($account, $simple ? 'reconnectXuanxuan' : 'loginXuanxuan', 'fail', $comment);
return $this->im->sendOutput(array('result' => 'fail', 'data' => $user));
}
if (isset($user->cidrs) && !$this->im->checkIPInCIDRs(helper::getRemoteIp(), $user->cidrs)) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->IPInvalid, 'messageResponsePack'));
$loginInfo = new stdclass();
$loginInfo->result = 'success';
$loginInfo->users = $user->id;
$loginInfo->method = 'userlogin';
$loginInfo->device = $device;
$loginInfo->lang = $lang;
/* Save client status and client lang of the user.*/
$userData = new stdclass();
$userData->id = $user->id;
$userData->clientStatus = $status;
$userData->clientLang = $this->session->clientLang;
$user = $this->im->userUpdate($userData);
$this->im->userAddAction($user->id, $simple ? 'reconnectXuanxuan' : 'loginXuanxuan', 'success', $comment);
/* Append signed time, backendUrl and status to user. */
$user->status = $status;
$loginInfo->data = $user;
$loginInfo = $this->im->formatOutput($loginInfo, 'userloginResponse', $returnRaw = true);
$userChatList = $this->im->chatGetListByUserID($user->id);
$botChat = in_array("$user->id&xuanbot", array_column($userChatList, 'gid'));
if(!$botChat)
{
$this->im->chatCreate("$user->id&xuanbot", '', 'bot', array($user->id), 0, false, $user->id);
$this->im->messageCreateXuanbotWelcomeNotify($user->id, version_compare($version, '7.0', 'lt'));
}
$chatList = $this->im->getChatListOutput($user->id, true, $botChat ? $userChatList : '');
$conferences = $this->im->getOpenConferencesOutput($user->id, true, $userChatList, true);
$output = array($loginInfo);
if(!empty($chatList)) $output[] = $chatList;
if(!empty($conferences)) $output[] = $conferences;
$response = $this->im->appendResponseHeader($output, $user->id, $user->id);
$this->im->userUpdateDevice($user->id, $device, 'login');
return $this->app->output($this->app->encrypt($response));
}
/**
* Logout.
*
* @param bool $normal
* @param int $userID
* @access public
* @return void
*/
public function userLogout($normal = false, $userID = 0)
{
$output = new stdClass();
$onlineUserIdList = array_keys($this->im->userGetList($status = 'online'));
if(!in_array($userID, $onlineUserIdList))
{
$this->im->userAddAction($userID, $normal ? 'logoutXuanxuan' : 'disconnectXuanxuan', 'fail');
$output->result = 'fail';
$output->data = $this->im->userGetByID($userID);
$output->users = $onlineUserIdList;
return $this->app->output($this->app->encrypt($output));
}
$user = new stdclass();
$user->id = $userID;
$user->clientStatus = 'offline';
$user = $this->im->userUpdate($user);
$user->status = $user->clientStatus;
$this->im->userAddAction($userID, $normal ? 'logoutXuanxuan' : 'disconnectXuanxuan', 'success');
if($this->im->conferenceIsUserOccupied($userID))
{
$this->im->conferenceRemoveUserFromConferences($userID);
$this->loadModel('conference')->removeUserFromSRS($userID);
}
$this->im->userUpdateDevice($user->id, isset($this->app->input['device']) ? $this->app->input['device'] : 'default');
session_destroy();
$onlineUsers = $this->im->userGetList($status = 'online');
$onlineUserIdList = array_keys($onlineUsers);
$output->result = 'success';
$output->data = $user;
$output->users = $onlineUserIdList;
return $this->im->sendOutput($output, 'userlogoutResponse');
}
/**
* Get user list.
*
* @param array $identities array of userIDs or accounts.
* @param int $userID
* @access public
* @return void
*/
public function userGetList($identities, $userID = 0)
{
$output = $this->im->getUserListOutput($identities, $userID, $returnRaw = false);
return $this->app->output($this->app->encrypt($output));
}
/**
* Get user id list by dept with pager and sort rule
*
* @param string $deptID
* @param object $pager
* @param string $orderBy
* @param array $exclude
* @param int $userID
* @access public
* @return array
*/
public function userGetListByDept($deptID, $pager, $orderBy, $exclude = array(), $onlySelf = false, $userID = 0)
{
if(empty($pager)) $pager = new stdclass();
if(empty($orderBy)) $orderBy = 'id_asc';
if(!isset($pager->pageID)) $pager->pageID = 1;
if(!isset($pager->recPerPage)) $pager->recPerPage = 50;
if(!isset($pager->recTotal)) $pager->recTotal = 0;
$this->app->loadClass('pager', $static = true);
$pager = new pager($pager->recTotal, $pager->recPerPage, $pager->pageID);
$list = $this->im->userGetIDListByDept($deptID, $exclude, $pager, $orderBy, $onlySelf);
$idList = array();
foreach($list as $id) $idList[] = (int)$id;
$output = new stdclass();
$output->result = 'success';
$output->users = array($userID);
$output->data = $idList;
$output->pager = new stdclass();
$output->pager->recPerPage = $pager->recPerPage;
$output->pager->pageID = $pager->pageID;
$output->pager->recTotal = $pager->recTotal;
$output->pager->data = array('dept' => $deptID, 'orderBy' => $orderBy);
return $this->im->sendOutput($output, 'usergetlistbydeptResponse');
}
/**
* Get deleted users with their user ids.
*
* @param array $idList
* @param int $userID
* @return void
* @deprecated Use "userGetList" instead
*/
public function userGetDeleted($idList, $userID)
{
$output = $this->im->getUserListOutput($idList, $userID);
return $this->app->output($this->app->encrypt($output));
}
/**
* Search for user with account / realname / pinyin in group / dept.
*
* @param string $search
* @param object $options {"chat": "3b320201-52e1-4061-90b2-23e750e8b6e0", "dept": 5, "limit": 51, "exclude": [3, 5, 7], "pager": {"pageID": 1, "recPerPage": 50, "recTotal": 0}}
* @param boolean $returnID
* @param integer $userID
* @access public
* @return void
*/
public function userSearch($search, $options = array(), $returnID = false, $userID = 0)
{
$pager = null;
if(property_exists($options, 'pager'))
{
$this->app->loadClass('pager', $static = true);
$pager = pager::init(isset($options->pager->recTotal) ? $options->pager->recTotal : 0, isset($options->pager->recPerPage) ? $options->pager->recPerPage : 50, isset($options->pager->pageID) ? $options->pager->pageID : 1);
unset($options->pager);
}
$output = new stdclass();
$output->result = 'success';
$output->users = array($userID);
$output->data = $this->im->userSearch($search, $options, $returnID, $pager);
$output->pager = $pager;
return $this->im->sendOutput($output, $returnID ? 'usersearchidResponse' : 'usersearchResponse');
}
/**
* Change a user.
*
* @param array $user
* @param int $userID
* @access public
* @return void
*/
public function userUpdate($user = array(), $userID = 0)
{
$user = (object)$user;
$user->id = $userID;
if(isset($user->status) && !empty($user->status))
{
$user->clientStatus = $user->status;
unset($user->status);
}
$user = $this->im->userUpdate($user);
if(dao::isError())
{
$this->im->userAddAction($userID, 'edit', 'fail');
return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Update user fail'), 'messageResponsePack');
}
$users = $this->im->userGetList($status = 'online');
$this->im->userAddAction($userID, 'edit', 'success');
$output = new stdclass();
$output->result = 'success';
$output->users = array_keys($users);
$output->data = $user;
return $this->im->sendOutput($output, 'userupdateResponse');
}
/**
* Upload or download settings.
*
* @param string $account
* @param string|array|object $settings
* @param int $userID
* @access public
* @return void
*/
public function userSyncSettings($account = '', $settings = '', $userID = 0)
{
/* Ignore $account param and use current user account */
if(empty($account)) $account = $this->dao->select('account')->from(TABLE_USER)->where('id')->eq($userID)->fetch('account');
$settingsObj = new stdclass();
$userSettings = json_decode($this->loadModel('setting')->getItem("owner=system&module=chat&section=settings&key=$account")) ?: new stdClass();
if(is_object($settings))
{
/* Upload the specified settings. */
$settingsObj = $settings;
foreach($settings as $key => $value) $userSettings->$key = $value;
$this->setting->setItem("system.chat.settings.$account", helper::jsonEncode($userSettings));
}
elseif(is_array($settings))
{
/* Download the specified settings. */
foreach($settings as $key) $settingsObj->$key = zget($userSettings, $key, '');
}
else
{
$isReset = $this->setting->getItem("owner=$account&module=user&section=clientSettings&key=reset");
if($isReset)
{
/* User setting has been reset */
$settingsObj->hash = '';
$settingsObj->reset = true;
$settingsObj->isReset = $isReset;
$this->loadModel('setting')->deleteItems("owner=system&module=chat&section=settings&key=$account");
$this->loadModel('setting')->deleteItems("owner=$account&module=user&section=clientSettings&key=reset");
}
elseif(isset($userSettings->hash) && $settings == $userSettings->hash)
{
/* User settings not change, only return hash */
$settingsObj->hash = $userSettings->hash;
}
else
{
/* Download all settings. */
$settingsObj = $userSettings;
}
}
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Save settings fail'), 'messageResponsePack');
$output = new stdclass();
$output->result = 'success';
$output->users = array($userID);
$output->data = $settingsObj;
return $this->im->sendOutput($output, 'usersyncsettingsResponse');
}
/**
* Set push device token to user table.
*
* @param string $deviceToken
* @param string $deviceType android|ios
* @param int $userID
* @access public
* @return void
*/
public function userSetDeviceToken($deviceToken = '', $deviceType = 'android', $userID = 0)
{
$result = $this->loadModel('user')->setDeviceToken($deviceToken, $deviceType, $userID);
return $this->im->sendOutput(array('result' => $result, 'users' => array($userID)), 'usersetdevicetokenResponse');
}
/**
* Get a new auth token for user's device.
*
* @param string $deviceType desktop|mobile|android|ios, optional
* @param string $deviceID
* @param int $userID
* @access public
* @return string|bool
*/
public function userGetAuthToken($deviceType = '', $deviceID = '', $userID = 0)
{
$tokenObj = $this->im->userGetAuthToken($userID, $deviceType, $deviceID);
$output = new stdclass();
$output->result = empty($tokenObj) ? 'fail' : 'success';
$output->users = array($userID);
$output->data = !empty($tokenObj) ? $tokenObj->token : '';
return $this->im->sendOutput($output, 'usergetauthtokenResponse');
}
/**
* Renew or just generate auth token for user's device.
*
* @param int $userID
* @param string $deviceType
* @param string $deviceID
* @access public
* @return object|bool
*/
public function userRenewAuthToken($deviceType = '', $deviceID = '', $userID = 0)
{
$tokenObj = $this->im->userRenewAuthToken($userID, $deviceType, $deviceID);
$output = new stdClass();
$output->result = empty($tokenObj) ? 'fail' : 'success';
$output->users = array($userID);
$output->data = !empty($tokenObj) ? $tokenObj->token : '';
return $this->im->sendOutput($output, 'usergetauthtokenResponse');
}
/**
* Get public chat list that user not join.
*
* @param int $userID
* @access public
* @return void
*/
public function chatGetPublicList($userID = 0)
{
$chatList = $this->im->chatGetPublicList($userID);
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Get public chat list fail'), 'messageResponsePack');
$output = new stdclass();
$output->result = 'success';
$output->users = $userID;
$output->data = $chatList;
return $this->im->sendOutput($output, 'chatgetpubliclistResponse');
}
/**
* Get chat list of a user.
*
* @param int $userID
* @access public
* @return void
*/
public function chatGetList($userID = 0)
{
$output = $this->im->getChatListOutput($userID);
return $this->im->sendOutput($output);
}
/**
* Get message count and last message id of chat.
*
* @param string $gid
* @param int $userID
* @access public
* @return void
*/
public function chatGetMessageInfo($gid, $userID = 0)
{
$chat = $this->im->chatGetByGid($gid, true);
if(is_array($chat->members) && !in_array($userID, $chat->members) && $chat->mergedDate == '0000-00-00 00:00:00') return $this->im->sendOutput(array('result' => 'fail', 'message' => 'No such chat, or you are not in the chat.'), 'messageResponsePack');
$chatInfo = new stdclass();
$chatInfo->lastMessage = intval($chat->lastMessage);
$chatInfo->messageCount = $this->im->chatgetMessageCount($gid);
$output = new stdclass();
$output->result = 'success';
$output->users = array($userID);
$output->data = $chatInfo;
return $this->im->sendOutput($output, 'chatgetmessageinfoResponse');
}
/**
* Get last messages of chats by gids.
*
* @param string|array $cgids
* @param int $userID
* @access public
* @return void
*/
public function chatGetLastMessage($cgids, $userID)
{
if(is_string($cgids)) $cgids = array($cgids);
/* Check if user is in those chats. */
$userChatList = $this->im->chatGetGidListByUserID($userID);
$cgids = array_intersect($cgids, $userChatList);
$output = new stdclass();
$output->result = 'success';
$output->users = array($userID);
$output->data = $this->im->messageGetLast($cgids);
return $this->im->sendOutput($output, 'chatgetlastmessageResponse');
}
/**
* Get members of a chat.
*
* @param string $gid
* @param int $userID
* @access public
* @return void
*/
public function chatGetMembers($gid = '', $userID = 0)
{
$chat = $this->im->chatGetByGid($gid, true, true);
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Get member list fail'));
$output = new stdclass();
$output->result = 'success';
$output->users = array($userID);
$data = new stdclass();
$data->gid = $gid;
$data->members = $chat->mergedDate == '0000-00-00 00:00:00' ? $chat->members : array($userID);
$output->data = $data;
return $this->im->sendOutput($output, 'chatgetmembersResponse');
}
/**
* Get detailed member list of a chat.
*
* @param string $gid
* @param object $pager
* @param string $orderBy
* @param string $search
* @param int $userID
* @access public
* @return void
*/
public function chatGetMemberDetails($gid, $pager = null, $orderBy = '', $search = '', $userID = 0)
{
$user = $this->im->userGetByID($userID);
if(empty($user->admin) || $user->admin != 'super') return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Unauthorized to get member details.'));
if(empty($pager)) $pager = new stdclass();
if(!isset($pager->pageID)) $pager->pageID = 1;
if(!isset($pager->recPerPage)) $pager->recPerPage = 10;
if(!isset($pager->recTotal)) $pager->recTotal = 0;
$this->app->loadClass('pager', $static = true);
$pager = new pager($pager->recTotal, $pager->recPerPage, $pager->pageID);
/* Search for members in chat. */
$memberIDs = array();
if(!empty($search))
{
$userSearchPager = pager::init(0, $pager->recPerPage, 1);
$memberIDs = $this->im->userSearch($search, array('chat' => $gid), true, $userSearchPager);
}
$details = $this->im->chatGetMemberDetails($gid, $pager, $orderBy, $memberIDs);
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Get chat details fail'));
$output = new stdclass();
$output->result = 'success';
$output->users = array($userID);
$output->data = $details->data;
$output->pager = $details->pager;
return $this->im->sendOutput($output, 'chatgetmemberdetailsResponse');
}
/**
* Create a chat.
*
* @param string $gid
* @param string $name
* @param string $type
* @param array $members
* @param int $subjectID
* @param bool $public true: the chat is public | false: the chat isn't public.
* @param int $userID
* @access public
* @return void
*/
public function chatCreate($gid = '', $name = '', $type = 'group', $members = array(), $subjectID = 0, $public = false, $userID = 0)
{
if($gid == 'notification' or $gid == 'littlexx') return $this->im->sendOutput(array('result' => 'success', 'users' =>$userID));
$chat = $this->im->chat->getByGid($gid, true);
if(!$chat)
{
$name = strip_tags($name);
$chat = $this->im->chat->create($gid, $name, $type, $members, $subjectID, $public, $userID);
}
$users = $this->im->userGetList($status = 'online', $chat->members);
if(dao::isError())
{
if($type == 'group') $this->im->chatAddAction(0, 'create', $userID, 'fail');
return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Create chat fail'), 'messageResponsePack');
}
$output = new stdclass();
$output->result = 'success';
$output->method = $this->app->getMethodName();
$output->users = array_keys($users);
$output->data = $chat;
if($type == 'group')
{
$this->im->chatAddAction($chat->id, 'create', $userID, 'success');
$broadcast = $this->im->messageCreateBroadcast('createChat', $chat, array_keys($users), $userID);
if($broadcast) $output = array($output, $broadcast);
return $this->im->sendOutputGroup($output);
}
return $this->im->sendOutput($output, 'chatcreateResponse');
}
/**
* Set admins of a chat.
*
* @param string $gid
* @param array $admins
* @param int $userID
* @access public
* @return void
*/
public function chatAddAdmins($gid = '', $admins = array(), $userID = 0)
{
$chat = $this->im->chat->getByGid($gid);
if(!$chat) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notExist), 'messageResponsePack');
$account = $this->dao->select('account')->from(TABLE_USER)->where('id')->eq($userID)->fetch('account');
if((empty($chat->ownedBy) && $chat->createdBy != $account) || (!empty($chat->ownedBy) && $chat->ownedBy != $account))
{
$user = $this->im->userGetByID($userID);
if(empty($user->admin) || $user->admin != 'super') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupCreator), 'messageResponsePack');
}
$account = $this->dao->select('account')->from(TABLE_USER)->where('id')->eq($userID)->fetch('account');
$sysAdmins = $this->dao->select('admins')->from(TABLE_COMPANY)->where('id')->eq($this->app->company->id)->fetch('admins');
$sysAdminArray = explode(',', $sysAdmins);
$super = in_array($account, $sysAdminArray) ? 'super' : '';
if($chat->archiveDate && $super != 'super')
{
$chat = $this->im->chat->getByGid($gid, true);
$output = new stdclass();
$output->result = 'success';
$output->users = array($userID);
$output->data = $chat;
return $this->im->sendOutput($output, 'chataddadminsResponse');
}
$chat = $this->im->chatAddAdmins($gid, $admins, $userID);
$users = $this->im->userGetList($status = 'online', $chat->members);
$comment = json_encode(array('admins' => $admins));
$this->im->chatAddAction($chat->id, 'addAdmins', $userID, 'success', $comment);
$users = array_keys($users);
$users[] = $userID;
$users = array_unique($users);
$output = new stdclass();
$output->result = 'success';
$output->users = $users;
$output->data = $chat;
return $this->im->sendOutput($output, 'chataddadminsResponse');
}
/**
* Remove admins of a chat.
*
* @param string $gid
* @param array $users
* @param int $userID
* @access public
* @return void
*/
public function chatRemoveAdmins($gid = '', $admins = array(), $userID = 0)
{
$chat = $this->im->chat->getByGid($gid);
if(!$chat) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notExist), 'messageResponsePack');
$account = $this->dao->select('account')->from(TABLE_USER)->where('id')->eq($userID)->fetch('account');
if((empty($chat->ownedBy) && $chat->createdBy != $account) || (!empty($chat->ownedBy) && $chat->ownedBy != $account))
{
$user = $this->im->userGetByID($userID);
if(empty($user->admin) || $user->admin != 'super') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupCreator), 'messageResponsePack');
}
$account = $this->dao->select('account')->from(TABLE_USER)->where('id')->eq($userID)->fetch('account');
$sysAdmins = $this->dao->select('admins')->from(TABLE_COMPANY)->where('id')->eq($this->app->company->id)->fetch('admins');
$sysAdminArray = explode(',', $sysAdmins);
$super = in_array($account, $sysAdminArray) ? 'super' : '';
if($chat->archiveDate && $super != 'super')
{
$chat = $this->im->chat->getByGid($gid, true);
$output = new stdclass();
$output->result = 'success';
$output->users = array($userID);
$output->data = $chat;
return $this->im->sendOutput($output, 'chatremoveadminsResponse');
}
$chat = $this->im->chatRemoveAdmins($gid, $admins, $userID);
$users = $this->im->userGetList($status = 'online', $chat->members);
$comment = json_encode(array('admins' => $admins));
$this->im->chatAddAction($chat->id, 'removeAdmins', $userID, 'success', $comment);
$users = array_keys($users);
$users[] = $userID;
$users = array_unique($users);
$output = new stdclass();
$output->result = 'success';
$output->users = $users;
$output->data = $chat;
return $this->im->sendOutput($output, 'chatremoveadminsResponse');
}
/**
* Pin messages of a chat.
*
* @param string $gid
* @param array $messageIds
* @param int $userID
* @access public
* @return void
*/
public function chatPinMessages($gid = '', $messageIds = array(), $userID = 0)
{
$chat = $this->im->chat->getByGid($gid);
if(!$chat) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notExist), 'messageResponsePack');
if(!$this->im->chatIsAdmin($chat, $userID)) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notAdmin), 'messageResponsePack');
if(!$chat->archiveDate)
{
$chat = $this->im->chatPinMessages($chat, $messageIds);
}
$users = $this->im->userGetList($status = 'online', $chat->members);
$output = new stdclass();
$output->result = 'success';
$output->users = array_keys($users);
$output->data = array('cgid' => $gid, 'pinned' => $messageIds, 'allPinned' => $chat->pinnedMessages);
return $this->im->sendOutput($output, 'chatpinmessagesResponse');
}
/**
* Unpin messages of a chat.
*
* @param string $gid
* @param array $messageIds
* @param int $userID
* @access public
* @return void
*/
public function chatUnpinMessages($gid = '', $messageIds = array(), $userID = 0)
{
$chat = $this->im->chat->getByGid($gid);
if(!$chat) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notExist), 'messageResponsePack');
if(!$this->im->chatIsAdmin($chat, $userID)) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notAdmin), 'messageResponsePack');
if(!$chat->archiveDate)
{
$chat = $this->im->chatUnpinMessages($chat, $messageIds);
}
$users = $this->im->userGetList($status = 'online', $chat->members);
$output = new stdclass();
$output->result = 'success';
$output->users = array_keys($users);
$output->data = array('cgid' => $gid, 'unpinned' => $messageIds, 'allPinned' => $chat->pinnedMessages);
return $this->im->sendOutput($output, 'chatunpinmessagesResponse');
}
/**
* Join a chat.
*
* @param string $gid
* @param int $userID
* @access public
* @return void
*/
public function chatJoin($gid = '', $userID = 0)
{
$chat = $this->im->chat->getByGid($gid);
if(!$chat) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notExist), 'messageResponsePack');
if($chat->type != 'group') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupChat), 'messageResponsePack');
if($chat->public == '0') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notPublic), 'messageResponsePack');
$this->im->chatJoin($gid, $userID);
$chat = $this->im->chat->getByGid($gid, true);
$users = $this->im->userGetList($status = 'online', $chat->members);
$users = array_keys($users);
$users[] = $userID;
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Join chat failed.'), 'messageResponsePack');
$output = new stdclass();
$output->result = 'success';
$output->method = $this->app->getMethodName();
$output->users = $users;
$output->data = $chat;
$broadcast = $this->im->messageCreateBroadcast('joinChat', $chat, $users, $userID);
if($broadcast)
{
$output = array($output, $broadcast);
return $this->im->sendOutputGroup($output);
}
return $this->im->sendOutput($output);
}
/**
* Leave a chat.
*
* @param string $gid
* @param int $userID
* @access public
* @return void
*/
public function chatLeave($gid = '', $userID = 0)
{
$chat = $this->im->chat->getByGid($gid);
if(!$chat) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notExist), 'messageResponsePack');
if($chat->type != 'group') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupChat), 'messageResponsePack');
$this->im->chatLeave($gid, $userID);
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Leave chat failed.'), 'messageResponsePack');
$chat = $this->im->chat->getByGid($gid, true);
$users = $this->im->userGetList($status = 'online', $chat->members);
$users = array_keys($users);
$users[] = $userID;
$output = new stdclass();
$output->result = 'success';
$output->method = $this->app->getMethodName();
$output->users = $users;
$output->data = $chat;
if(empty($chat->dismissDate))
{
$broadcast = $this->im->messageCreateBroadcast('leaveChat', $chat, $users, $userID);
if($broadcast)
{
$output = array($output, $broadcast);
return $this->im->sendOutputGroup($output);
}
}
return $this->im->sendOutput($output, 'chatleaveResponse');
}
/**
* Change the name of a chat.
*
* @param string $gid
* @param string $name
* @param int $userID
* @access public
* @return void
*/
public function chatRename($gid = '', $name = '', $userID = 0)
{
$chat = $this->im->chat->getByGid($gid);
if(!$chat) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notExist), 'messageResponsePack');
if($chat->archiveDate) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->operationNotSupportedOnArchivedChat), 'messageResponsePack');
$account = $this->dao->select('account')->from(TABLE_USER)->where('id')->eq($userID)->fetch('account');
$sysAdmins = $this->dao->select('admins')->from(TABLE_COMPANY)->where('id')->eq($this->app->company->id)->fetch('admins');
$sysAdminArray = explode(',', $sysAdmins);
$super = in_array($account, $sysAdminArray) ? 'super' : '';
if(!$this->im->chatIsAdmin($chat, $userID) && $super != 'super') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notAdmin), 'messageResponsePack');
$isPrivateChat = $gid == "$userID&$userID";
if($chat->type != 'group' && $chat->type != 'system' && !$isPrivateChat) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupChat), 'messageResponsePack');
if(mb_strlen($name, 'utf8') > 16) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->chatNameTooLong), 'messageResponsePack');
$chat->name = strip_tags($name);
$chatID = $chat->id;
$comment = json_encode(array('name' => $name));
$chat = $this->im->chatUpdate($chat, $userID);
if(dao::isError())
{
$this->im->chatAddAction($chatID, 'rename', $userID, 'fail', $comment);
return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Rename chat fail.'), 'messageResponsePack');
}
$this->im->chatAddAction($chatID, 'rename', $userID, 'success', $comment);
$users = $this->im->userGetList($status = 'online', $chat->members);
$output = new stdclass();
$output->result = 'success';
$output->method = $this->app->getMethodName();
$output->users = array_keys($users);
$output->data = $chat;
$broadcast = $this->im->messageCreateBroadcast($isPrivateChat ? 'renamePrivate' : 'renameChat', $chat, array_keys($users), $userID);
if($broadcast)
{
$output = array($output, $broadcast);
return $this->im->sendOutputGroup($output);
}
return $this->im->sendOutput($output);
}
/**
* Dismiss a chat
*
* @param string $gid
* @param int $userID
* @access public
* @return void
*/
public function chatDismiss($gid = '', $userID = 0)
{
$chat = $this->im->chat->getByGid($gid);
if(!$chat) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notExist), 'messageResponsePack');
if($chat->type != 'group') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupChat), 'messageResponsePack');
$account = $this->dao->select('account')->from(TABLE_USER)->where('id')->eq($userID)->fetch('account');
if(empty($chat->ownedBy) && $chat->createdBy != $account) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupCreator), 'messageResponsePack');
if(!empty($chat->ownedBy) && $chat->ownedBy != $account) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupCreator), 'messageResponsePack');
$chat->dismissDate = helper::now();
$chatID = $chat->id;
$chat = $this->im->chatUpdate($chat, $userID);
if(dao::isError())
{
$this->im->chatAddAction($chatID, 'dismiss', $userID, 'fail');
return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Dismiss chat fail.'), 'messageResponsePack');
}
$this->im->chatAddAction($chatID, 'dismiss', $userID, 'success');
$users = $this->im->userGetList($status = 'online', $chat->members);
$output = new stdclass();
$output->result = 'success';
$output->method = $this->app->getMethodName();
$output->users = array_keys($users);
$output->data = $chat;
$broadcast = $this->im->messageCreateBroadcast('dismissChat', $chat, array_keys($users), $userID);
if($broadcast)
{
$output = array($output, $broadcast);
return $this->im->sendOutputGroup($output);
}
return $this->im->sendOutput($output);
}
/**
* Change the committers of a chat
*
* @param string $gid
* @param string $committers
* @param int $userID
* @access public
* @return void
*/
public function chatSetCommitters($gid = '', $committers = '', $userID = 0)
{
$chat = $this->im->chat->getByGid($gid);
if(!$chat) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notExist), 'messageResponsePack');
if($chat->type != 'group' && $chat->type != 'system') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupChat), 'messageResponsePack');
$chat->committers = $committers;
$chat = $this->im->chatUpdate($chat, $userID);
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Set chat committers fail.'), 'messageResponsePack');
$users = $this->im->userGetList($status = 'online', $chat->members);
$output = new stdclass();
$output->result = 'success';
$output->users = array_keys($users);
$output->data = $chat;
return $this->im->sendOutput($output, 'chatsetcommittersResponse');
}
/**
* Change a chat to be public or not.
*
* @param string $gid
* @param string $visible 0|1
* @param int $userID
* @access public
* @return void
*/
public function chatSetVisibility($gid = '', $visible = '1', $userID = 0)
{
$chat = $this->im->chat->getByGid($gid);
if(!$chat) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notExist), 'messageResponsePack');
if($chat->type != 'group') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupChat), 'messageResponsePack');
if($chat->archiveDate) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->operationNotSupportedOnArchivedChat), 'messageResponsePack');
$chatID = $chat->id;
$chat->public = $visible ? '1' : '0';
$chat->lastActiveTime = empty($chat->lastActiveTime) ? '0000-00-00 00:00:00' : date('Y-m-d H:i:s', $chat->lastActiveTime);
$chat = $this->im->chatUpdate($chat, $userID);
if(dao::isError())
{
$this->im->chatAddAction($chatID, $visible ? 'bepublic' : 'beprivate', $userID, 'fail');
return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Set chat visibility fail.'), 'messageResponsePack');
}
$this->im->chatAddAction($chatID, $visible ? 'bepublic' : 'beprivate', $userID, 'success');
$users = $this->im->userGetList($status = 'online', $chat->members);
$output = new stdclass();
$output->result = 'success';
$output->users = array_keys($users);
$output->data = $chat;
return $this->im->sendOutput($output, 'chatsetvisibilityResponse');
}
/**
* Star or cancel star a chat.
*
* @param bool $star true: star a chat | false: cancel star a chat.
* @param string $gid
* @param int $userID
* @access public
* @return void
*/
public function chatStar($star = true, $gid = '', $userID = 0)
{
$this->im->chatStar($star, $gid, $userID);
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Operate fail.'), 'messageResponsePack');
$output = new stdclass();
$output->result = 'success';
$output->users = $userID;
$output->data = new stdclass();
$output->data->gid = $gid;
$output->data->star = $star;
return $this->im->sendOutput($output, 'chatstarResponse');
}
/**
* Archive a chat or vice versa.
*
* @param bool $archive
* @param string $gid
* @param int $userID
* @access public
* @return void
*/
public function chatArchive($archive = true, $gid = '', $userID = 0)
{
$chat = $this->im->chat->getByGid($gid, false, false);
if(!$chat) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notExist), 'messageResponsePack');
if($chat->type != 'group') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupChat), 'messageResponsePack');
$account = $this->dao->select('account')->from(TABLE_USER)->where('id')->eq($userID)->fetch('account');
$account = $this->dao->select('account')->from(TABLE_USER)->where('id')->eq($userID)->fetch('account');
$sysAdmins = $this->dao->select('admins')->from(TABLE_COMPANY)->where('id')->eq($this->app->company->id)->fetch('admins');
$sysAdminArray = explode(',', $sysAdmins);
$super = in_array($account, $sysAdminArray) ? 'super' : '';
if(!empty($chat->ownedBy) && $chat->ownedBy != $account && $super != 'super') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupCreator), 'messageResponsePack');
if($archive)
{
$chat->archiveDate = helper::now();
}
else
{
$chat->archiveDate = '0000-00-00 00:00:00';
}
$chatID = $chat->id;
$chat = $this->im->chatUpdate($chat, $userID);
if(dao::isError())
{
$this->im->chatAddAction($chatID, 'archive', $userID, 'fail');
return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Archive chat fail.'), 'messageResponsePack');
}
$this->im->chatAddAction($chatID, 'archive', $userID, 'success');
$users = $this->im->userGetList($status = 'online', $chat->members);
$output = new stdclass();
$output->result = 'success';
$output->method = $this->app->getMethodName();
$output->users = array_keys($users);
$output->data = $chat;
$broadcast = $this->im->messageCreateBroadcast($archive ? 'archiveChat' : 'unarchiveChat', $chat, array_keys($users), $userID);
if($broadcast)
{
$output = array($output, $broadcast);
return $this->im->sendOutputGroup($output);
}
return $this->im->sendOutput($output);
}
/**
* Hide or display a chat.
*
* @param bool $hide true: hide a chat | false: display a chat.
* @param string $gid
* @param int $userID
* @access public
* @return void
*/
public function chatHide($hide = true, $gid = '', $userID = 0)
{
// discard chatHide from v6.6. For old xxc versions use chatMute and chatFreeze instead.
$this->im->chatMute($hide, $gid, $userID);
$this->im->chatFreeze($hide, $gid, $userID);
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Toggle chat fail.'), 'messageResponsePack');
$outputs = array();
$chatHideResponse = new stdclass();
$chatHideResponse->result = 'success';
$chatHideResponse->users = $userID;
$chatHideResponse->method = 'chathide';
$chatHideResponse->data = new stdclass();
$chatHideResponse->data->gid = $gid;
$chatHideResponse->data->hide = false;
$outputs[] = $chatHideResponse;
$chatMuteResponse = new stdclass();
$chatMuteResponse->result = 'success';
$chatMuteResponse->users = $userID;
$chatMuteResponse->method = 'chatmute';
$chatMuteResponse->data = new stdclass();
$chatMuteResponse->data->gid = $gid;
$chatMuteResponse->data->mute = $hide;
$outputs[] = $chatMuteResponse;
$chatFreezeResponse = new stdclass();
$chatFreezeResponse->result = 'success';
$chatFreezeResponse->users = $userID;
$chatFreezeResponse->method = 'chatfreeze';
$chatFreezeResponse->data = new stdclass();
$chatFreezeResponse->data->gid = $gid;
$chatFreezeResponse->data->freeze = $hide;
$outputs[] = $chatFreezeResponse;
return $this->im->sendoutputGroup($outputs);
}
/**
* Mute a chat.
*
* @param string $gid
* @param bool $mute true: mute a chat | false: cacel mute a chat.
* @param int $userID
* @access public
* @return void
*/
public function chatMute($mute = true, $gid = '', $userID = 0)
{
$this->im->chatMute($mute, $gid, $userID);
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Mute chat fail.'), 'messageResponsePack');
$output = new stdclass();
$output->result = 'success';
$output->users = $userID;
$output->data = new stdclass();
$output->data->gid = $gid;
$output->data->mute = $mute;
return $this->im->sendOutput($output, 'chatmuteResponse');
}
/**
* Freeze a chat.
*
* @param string $gid
* @param bool $freeze true: freeze a chat | false: unfreeze a chat.
* @param int $userID
* @access public
* @return void
*/
public function chatFreeze($freeze = true, $gid = '', $userID = 0)
{
$this->im->chatFreeze($freeze, $gid, $userID);
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Set chat freeze fail.'), 'messageResponsePack');
$output = new stdclass();
$output->result = 'success';
$output->users = $userID;
$output->data = new stdclass();
$output->data->gid = $gid;
$output->data->freeze = $freeze;
return $this->im->sendOutput($output, 'chatfreezeResponse');
}
/**
* Set category for a chat
*
* @param array $gids
* @param string $category
* @param int $userID
* @access public
* @return void
*/
public function chatSetCategory($gids = array(), $category = '', $userID = 0)
{
$this->im->chat->setCategory($gids, $category, $userID);
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Set chat category fail.'), 'messageResponsePack');
$output = new stdclass();
$output->result = 'success';
$output->users = $userID;
$output->data = new stdclass();
$output->data->gids = $gids;
$output->data->category = $category;
return $this->im->sendOutput($output, 'chatsetcategoryResponse');
}
/**
* Invite members to a chat.
*
* @param string $gid
* @param array $members
* @param int $userID
* @access public
* @return void
*/
public function chatInvite($gid = '', $members = array(), $userID = 0)
{
$chat = $this->im->chat->getByGid($gid, true);
$user = $this->im->userGetById($userID);
if(!$chat) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notExist), 'messageResponsePack');
if(!$this->im->chatIsAdmin($chat, $userID) && $chat->adminInvite == '1' && $chat->public == '0' && $user->admin !='super') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->adminCanInvite), 'messageResponsePack');
if($user->admin != 'super' && !in_array($userID, $chat->members)) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->userNotInGroup), 'messageResponsePack');
if($chat->type != 'group') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupChat), 'messageResponsePack');
$joinedMembers = array();
foreach($members as $member)
{
$result = $this->im->chatJoin($gid, $member);
if(is_int($result)) $joinedMembers[] = $result;
}
$chat = $this->im->chat->getByGid($gid, true, true, true);
$users = $this->im->userGetList($status = 'online', $chat->members);
$comment = json_encode(array('members' => $members));
if(dao::isError())
{
$this->im->chatAddAction($chat->id, 'invite', $userID, 'fail', $comment);
return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Invite chat member fail.'), 'messageResponsePack');
}
$this->im->chatAddAction($chat->id, 'invite', $userID, 'success', $comment);
$output = new stdclass();
$output->result = 'success';
$output->method = $this->app->getMethodName();
$output->users = array_keys($users);
$output->data = $chat;
if($user->admin == 'super')
{
$output->users[] = (int)$userID;
$output->users = array_unique($output->users);
}
$members = array_diff($members, $joinedMembers);
if(!empty($members))
{
$broadcast = $this->im->messageCreateBroadcast('inviteUser', $chat, $output->users, $userID, $members);
if($broadcast)
{
$output = array($output, $broadcast);
return $this->im->sendOutputGroup($output);
}
}
return $this->im->sendOutput($output, 'chatinviteResponse');
}
/**
* Kick members from a chat.
*
* @param string $gid
* @param array $users
* @param int $userID
* @access public
* @return void
*/
public function chatKick($gid = '', $users = array(), $userID = 0)
{
$chat = $this->im->chat->getByGid($gid);
if(!$chat) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notExist), 'messageResponsePack');
if(!$this->im->chatIsAdmin($gid, $userID))
{
$user = $this->im->userGetByID($userID);
if(empty($user->admin) || $user->admin != 'super') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupCreator), 'messageResponsePack');
}
if($chat->type != 'group') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupChat), 'messageResponsePack');
$groupOwner = $this->dao->select('tu.id')->from(TABLE_IM_CHAT)->alias('tc')->leftJoin(TABLE_USER)->alias('tu')->on('tc.ownedBy=tu.account')->where('tc.gid')->eq($gid)->fetch('id');
if(!empty($groupOwner) && in_array($groupOwner, $users))
{
$users = array_diff($users, array($groupOwner));
}
if(empty($users))
{
return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->canNotDelOwner), 'messageResponsePack');
}
foreach($users as $user) $this->im->chatLeave($gid, $user);
$chat = $this->im->chat->getByGid($gid, true);
$members = $this->im->userGetList($status = 'online', $chat->members);
$members = array_keys($members);
$members = array_merge($members, $users);
$comment = json_encode(array('members' => $users));
if(dao::isError())
{
$this->im->chatAddAction($chat->id, 'kick', $userID, 'fail', $comment);
return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Kick chat member fail.'), 'messageResponsePack');
}
$this->im->chatAddAction($chat->id, 'kick', $userID, 'success', $comment);
$users = $members;
$users[] = $userID;
$users = array_unique($users);
$output = new stdclass();
$output->result = 'success';
$output->users = $users;
$output->data = $chat;
return $this->im->sendOutput($output, 'chatkickResponse');
}
/**
* Get history messages of a chat.
*
* @param string $gid
* @param int $recPerPage
* @param int $pageID
* @param int $recTotal
* @param bool $continued
* @param int $startDate
* @param int $userID
* @access public
* @return void
* @deprecated The method is unnecessary in new versions.
*/
public function chatGetHistory($gid = '', $recPerPage = 20, $pageID = 1, $recTotal = 0, $continued = false, $startDate = 0, $userID = 0)
{
if($startDate) $startDate = date('Y-m-d H:i:s', $startDate);
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
if($gid)
{
$messageList = $this->im->message->getListByCgid($gid, $pager, $startDate);
}
else
{
$messageList = $this->im->message->getList('', $idList = array(), $pager, $startDate);
}
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Get history fail'), 'messageResponsePack');
$output = new stdclass();
$output->result = 'success';
$output->users = array($userID);
$output->data = $messageList;
$output->pager = new stdclass();
$output->pager->recPerPage = $pager->recPerPage;
$output->pager->pageID = $pager->pageID;
$output->pager->recTotal = $pager->recTotal;
$output->pager->gid = $gid;
$output->pager->continued = $continued;
return $this->im->sendOutput($output, 'chatgethistoryResponse');
}
/**
* Set last read message for a chat
*
* @param string $gid
* @param int $lastReadMessageID
* @param int $userID
* @access public
* @return void
*/
public function chatSetLastReadMessage($gid, $lastReadMessageID = 0, $userID = 0)
{
$this->im->chatSetLastReadMessage($gid, $lastReadMessageID, $userID);
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => "Set last read message fail for chat $gid."), 'messageResponsePack');
$output = new stdclass();
$output->result = 'success';
$output->users = $userID;
$output->data = new stdclass();
$output->data->gid = $gid;
$output->data->id = $lastReadMessageID;
return $this->im->sendOutput($output, 'chatsetlastreadmessageResponse');
}
/**
* Merge chat by gid.
*
* @param string $gid
* @param string $targetGid
* @param int $userID
* @access public
* @return void
*/
public function chatMerge($gid, $targetGid, $userID)
{
$chat = $this->im->chatGetByGid($gid, true);
$targetChat = $this->im->chatGetByGid($targetGid, true);
if(empty($chat) || empty($targetChat)) return $this->im->sendOutput(array('result' => 'fail', 'message' => "Get chats fail, check if chats exist."), 'messageResponsePack');
if($chat->archiveDate) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->operationNotSupportedOnArchivedChat), 'messageResponsePack');
if($targetChat->archiveDate) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->operationNotSupportedOnArchivedChat), 'messageResponsePack');
$newMembers = array_diff($chat->members, $targetChat->members);
$targetChat = $this->im->chatMerge($chat, $targetChat, $userID);
if(empty($targetChat)) return $this->im->sendOutput(array('result' => 'fail', 'message' => "Unable to merge chat $gid into chat $targetGid."), 'messageResponsePack');
$mergeNoticeChat = $chat;
$mergeNoticeChat->intoName = $targetChat->name;
$mergeNotice = $this->im->messageCreateBroadcast('chatMerged', $mergeNoticeChat, $mergeNoticeChat->members, $userID);
$chat->members = array();
$targetChatName = $targetChat->name;
$broadcastChat = $targetChat;
$broadcastChat->name = $chat->name; // Use merged chat name in broadcast.
$mergeBroadcast = $this->im->messageCreateBroadcast(empty($newMembers) ? 'mergeChat' : 'mergeChatWithMembers', $broadcastChat, $targetChat->members, $userID, $newMembers);
$targetChat->name = $targetChatName; // Restore target chat name.
$leaveOutput = new stdclass();
$leaveOutput->result = 'success';
$leaveOutput->method = 'chatLeave';
$leaveOutput->users = $targetChat->members;
$leaveOutput->data = $chat;
$joinOutput = new stdclass();
$joinOutput->result = 'success';
$joinOutput->method = 'chatJoin';
$joinOutput->users = $targetChat->members;
$joinOutput->data = $targetChat;
$outputGroup = array($leaveOutput, $joinOutput, $mergeBroadcast, $mergeNotice);
$user = $this->im->userGetById($userID);
if($user->admin == 'super')
{
$targetChat->members[] = (int)$userID;
$leaveOutput->users = array_unique($leaveOutput->users);
$mergeOutput = new stdclass();
$mergeOutput->result = 'success';
$mergeOutput->users = $userID;
$mergeOutput->method = 'chatMerge';
$mergeOutput->data = new stdclass();
$mergeOutput->data->targetGid = $targetGid;
$outputGroup[] = $mergeOutput;
}
return $this->im->sendOutputGroup($outputGroup);
}
/**
* Set last read message for a chat
*
* @param string $gid
* @param int $lastReadMessageIndex
* @param int $userID
* @access public
* @return void
*/
public function chatSetLastReadMessageByIndex($gid, $lastReadMessageIndex = 0, $userID = 0)
{
$this->im->chatSetLastReadMessageByIndex($gid, $lastReadMessageIndex, $userID);
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => "Set last read message fail for chat $gid."), 'messageResponsePack');
$output = new stdclass();
$output->result = 'success';
$output->users = $userID;
$output->data = new stdclass();
$output->data->gid = $gid;
$output->data->id = $lastReadMessageIndex;
return $this->im->sendOutput($output, 'chatsetlastreadmessageResponse');
}
/**
* Get chat by gid.
*
* @param string $gid
* @access public
* @return void
*/
public function chatGetByGid($gid)
{
$output = new stdclass();
$output->module = 'im';
$output->method = 'chatgetbygid';
$output->result = 'success';
$output->data = new stdclass();
$output->data = $this->im->chatGetByGid($gid, true);
return $this->im->sendOutput($output, 'chatgetbygidResponse');
}
/**
* Change ownership of group.
*
* @param string $gid
* @param int $ownerUserID new owner id
* @param int $userID
* @access public
* @return void
*/
public function chatChangeOwnership($gid, $ownerUserID, $userID = 0)
{
$chat = $this->im->chatGetByGid($gid, true);
/* Check if new owner is a member of chat. */
if(!in_array($ownerUserID, $chat->members)) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Cannot change ownership of chat, new owner must be in the chat.'), 'messageResponsePack');
$account = $this->dao->select('account')->from(TABLE_USER)->where('id')->eq($userID)->fetch('account');
$sysAdmins = $this->dao->select('admins')->from(TABLE_COMPANY)->where('id')->eq($this->app->company->id)->fetch('admins');
$sysAdminArray = explode(',', $sysAdmins);
$super = in_array($account, $sysAdminArray) ? 'super' : '';
if($chat->archiveDate && $super != 'super') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->operationNotSupportedOnArchivedChat), 'messageResponsePack');
/* Check if current user is a member of chat or super admin. */
$user = $this->im->userGetByID($userID);
$byAdmin = !empty($user->admin) && $user->admin == 'super';
if(!$byAdmin && !in_array($userID, $chat->members)) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Cannot change ownership of chat, current user must be in the chat.'));
$result = $this->im->chatChangeOwnership($chat, $ownerUserID, $userID, $byAdmin);
if(empty($result)) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Change ownership failed.'), 'messageResponsePack');
$output = new stdclass();
$output->method = 'chatchangeownership';
$output->result = 'success';
$output->users = $chat->members;
$output->data = $result;
if($byAdmin)
{
$output->users[] = $userID;
$output->users = array_unique($output->users);
}
$users = $this->im->userGetList($status = 'online', $chat->members);
$this->im->chatAddAction($chat->id, 'changeOwnership', $userID, 'success');
$broadcast = $this->im->messageCreateBroadcast('changeChatOwnership' . ($byAdmin ? 'ByAdmin' : ''), $chat, array_keys($users), $ownerUserID, $chat->members);
if($broadcast) $output = array($output, $broadcast);
return $this->im->sendOutputGroup($output);
}
/**
* Retract a message.
*
* @param array $messages
* @param int $userID
* @access public
* @return void
*/
public function messageRetract($messages = array(), $userID = 0)
{
$chats = array();
foreach($messages as $key => $message)
{
$message = (object) $message;
$chats[$message->cgid] = $message->cgid;
if(isset($message->type) && $message->type == 'broadcast') unset($messages[$key]);
}
$message = (object) current($messages);
$chat = $this->im->chat->getByGid($message->cgid, $getMembers = true);
$onlineUsers = $this->im->userGetList($status = 'online', $chat->members);
$messages = $this->im->messageRetract($message->gid, $this->im->chatIsAdmin($chat, $userID), $userID);
if(dao::isError() && count($messages) == 0) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Retract message fail.'), 'messageResponsePack');
$output = new stdclass();
$output->result = 'success';
$output->users = array_keys($onlineUsers);
$output->data = $messages;
return $this->im->sendOutput($output, 'messageretractResponse');
}
/**
* Send message to a chat.
*
* @param array $messages
* @param int $userID
* @access public
* @return void
*/
public function messageSend($messages = array(), $userID = 0, $version = '', $device = 'desktop')
{
/* Check if the messages belong to the same chat. */
$chats = array();
foreach($messages as $key => $message)
{
$message = (object) $message;
$chats[$message->cgid] = $message->cgid;
}
$message = (object) current($messages);
$members = explode('&', $message->cgid);
$isOne2OneChat = (count($members) == 2);
if($message->user != $userID) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notSameUser), 'messageResponsePack');
$chat = $this->im->chat->getByGid($message->cgid, $getMembers = true);
/* Call bots if is chat with bot. */
$responsesFromBot = array();
if($isOne2OneChat && in_array('xuanbot', $members)) // TODO: check for chat type later.
{
$members = array_filter($members, static function ($member) {
return is_numeric($member);
});
$repliesFromBot = $this->im->botProcessMessage($message, $userID);
$messagesFromBot = $repliesFromBot->messages;
if(version_compare($version, '7.0', 'lt') && $device != 'mobile')
{
foreach($messagesFromBot as $message)
{
$message->user = -1;
}
}
$responsesFromBot = $repliesFromBot->responses;
$messages = array_merge($messages, $messagesFromBot);
}
$newChat = false;
if(!$chat && $isOne2OneChat)
{
$newChat = true;
$chat = $this->im->chatcreate($message->cgid, '', 'one2one', $members, 0, false, $userID);
if(dao::isError())
{
return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'Create chat fail.'), 'messageResponsePack');
}
}
if($chat->archiveDate) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->operationNotSupportedOnArchivedChat), 'messageResponsePack');
/* Check whether the logon user can send message in chat. */
$isCommitter = $this->im->chatIsCommitter($message, $userID, $chat);
if($isCommitter !== true) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->cantChat), 'messageResponsePack');
/* If message is a bulletin, check if user is an admin. */
if($message->type == 'bulletin')
{
$isAdmin = $this->im->chatIsAdmin($chat, $userID);
if(!$isAdmin) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'Only admins can send bulletin messages.'), 'messageResponsePack');
}
$onlineUsers = array($userID);
$offlineUsers = array();
$users = $this->im->userGetList($status = '', $chat->members);
foreach($users as $id => $user)
{
if($id == $userID) continue;
if($user->clientStatus == 'offline') $offlineUsers[] = $id;
if($user->clientStatus != 'offline') $onlineUsers[] = $id;
}
/* Create messages. */
$messages = $this->im->messageCreate($messages, $userID);
if(empty($messages)) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'No message created.'), 'messageResponsePack');
$this->im->messageSaveOfflineList($messages, $offlineUsers);
/* Push message to offline users */
if(dao::isError()) return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Send message fail'), 'messageResponsePack');
$output = new stdclass();
$output->result = 'success';
$output->method = 'messagesend';
$output->users = $onlineUsers;
$output->data = $messages;
$outputs = array_merge(array($output), $responsesFromBot);
if($newChat)
{
$chatOutput = new stdclass();
$chatOutput->module = 'im';
$chatOutput->method = 'chatcreate';
$chatOutput->result = 'success';
$chatOutput->users = $onlineUsers;
$chatOutput->data = $chat;
array_unshift($outputs, $chatOutput);
return $this->im->sendOutputGroup($outputs);
}
return $this->im->sendOutputGroup($outputs);
}
/**
* Get messages from chat by ID.
*
* @param string $cgid
* @param array $idList
* @param int $userID
* @access public
* @return void
*/
public function messageGetList($cgid, $idList, $userID = 0)
{
$chat = $this->im->chatGetByGid($cgid, true);
if(is_array($chat->members) && !in_array($userID, $chat->members) && $chat->mergedDate == '0000-00-00 00:00:00') return $this->im->sendOutput(array('result' => 'fail', 'message' => 'No such chat, or you are not in the chat.'), 'messageResponsePack');
$messages = $this->im->messageGetList($cgid, $idList);
$output = new stdclass();
$output->result = 'success';
$output->method = 'messagegetlist';
$output->users = array($userID);
$output->data = $messages;
return $this->im->sendOutput($output, 'messagegetlistResponse');
}
/**
* Get messages from chat by indexes.
*
* @param string $cgid
* @param array $indexList
* @param int $userID
* @access public
* @return void
*/
public function messageGetListByIndexes($cgid, $indexList, $userID = 0)
{
$members = $this->im->chatGetMembers($cgid, true);
if(is_array($members) && !in_array($userID, $members)) $this->im->sendOutput(array('result' => 'fail', 'message' => 'No such chat, or you are not in the chat.'), 'messageResponsePack');
$messages = $this->im->messageGetListByIndexes($cgid, $indexList);
$output = new stdclass();
$output->result = 'success';
$output->method = 'messagegetlistbyindexes';
$output->users = array($userID);
$output->data = $messages;
return $this->im->sendOutput($output, 'messagegetlistbyindexesResponse');
}
/**
* Sync message from $fromID.
*
* @param string $cgid
* @param int $fromID
* @param bool $reverse
* @param int $limit
* @param bool $returnID
* @param int $userID
* @access public
* @return void
*/
public function messageSync($cgid, $fromID, $reverse = false, $limit = 50, $returnID = false, $userID = 0)
{
$chat = $this->im->chatGetByGid($cgid, true);
if(is_array($chat->members) && !in_array($userID, $chat->members) && $chat->mergedDate == '0000-00-00 00:00:00') return $this->im->sendOutput(array('result' => 'fail', 'message' => 'No such chat, or you are not in the chat.'), 'messageResponsePack');
$messages = $this->im->messageGetListAroundIDForUser($cgid, $fromID, $reverse, $limit, $userID, $returnID);
$output = new stdclass();
$output->result = 'success';
$output->method = 'messagesync';
$output->users = array($userID);
$output->data = $messages;
return $this->im->sendOutput($output, $returnID ? 'messagesyncidResponse' :'messagesyncResponse');
}
/**
* Sync message by indexIds.
*
* @param string $cgid
* @param array $indexList
* @param bool $reverse
* @param bool $returnID
* @param int $userID
* @access public
* @return void
*/
public function messageSyncByIndexes($cgid, $indexList, $reverse = false, $returnID = false, $userID = 0)
{
$members = $this->im->chatGetMembers($cgid, true);
if(is_array($members) && !in_array($userID, $members)) $this->im->sendOutput(array('result' => 'fail', 'message' => 'No such chat, or you are not in the chat.'), 'messageResponsePack');
$messages = $this->im->messageGetListAroundIDByIndexes($cgid, $indexList, $reverse, $returnID);
$output = new stdclass();
$output->result = 'success';
$output->method = 'messagesyncbyindexes';
$output->users = array($userID);
$output->data = $messages;
return $this->im->sendOutput($output, $returnID ? 'messagesyncidResponse' :'messagesyncResponse');
}
/**
* Sync messages since last logout.
*
* @param bool $full whether to lookup partitions or not.
* @param int $userID
* @access public
* @return void
*/
public function messageSyncSinceOffline($full = false, $userID = 0)
{
$messages = $this->im->messageGetOfflineList($full, $userID);
$output = new stdclass();
$output->result = 'success';
$output->method = 'messagesyncsinceoffline';
$output->users = array($userID);
$output->data = $messages;
return $this->im->sendOutput($output, 'messagesyncsinceofflineResponse');
}
/**
* Sync missed messages. (Messages that are read but not synced to client.)
*
* @param int $lastKnownMessage
* @param int $userID
* @access public
* @return void
*/
public function messageSyncMissed($lastKnownMessage, $userID = 0)
{
$messages = $this->im->messageGetMissedByLastKnown($lastKnownMessage, $userID);
$output = new stdclass();
$output->result = 'success';
$output->method = 'messagesyncmissed';
$output->users = array($userID);
$output->data = $messages;
return $this->im->sendOutput($output, 'messagesyncmissedResponse');
}
/**
* Get conference of chat, returns confernce object if conference is open.
*
* @param string $chatID
* @param int $userID
* @param string $version
* @param string $device
* @return void
*/
public function conferenceGetByChat($chatID, $userID = 0, $version = '', $device = 'desktop')
{
$chat = $this->im->chatGetByGidForUser($chatID, $userID);
if(empty($chat)) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'No such chat, or you are not in the chat.'), 'messageResponsePack');
$output = new stdclass();
$output->result = 'success';
$output->method = 'conferencegetbychat';
$output->users = array($userID);
$output->data = array();
$conference = $this->im->conferenceGetByChatID($chatID);
if(empty($conference)) return $this->im->sendOutput($output, 'conferencegetbychatResponse');
$output->data = array($conference);
return $this->im->sendOutput($output, 'conferencegetbychatResponse');
}
/**
* Create a conference for a chat.
*
* @param string $chatID
* @param array $invitee
* @param int $userID
* @access public
* @return void
*/
public function conferenceCreate($chatID, $invitee = array(), $userID = 0, $version = '', $device = 'desktop')
{
$this->loadModel('conference');
if(!$this->conference->isEnabled()) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => $this->lang->im->owtIsDisabled), 'messageResponsePack');
$privateChatMembers = explode('&', $chatID);
$isOne2OneChat = (count($privateChatMembers) == 2);
$chat = $this->im->chatGetByGidForUser($chatID, $userID);
if(empty($chat))
{
if($isOne2OneChat)
{
$chat = $this->im->chatcreate($chatID, '', 'one2one', $privateChatMembers, 0, false, $userID);
$chatCreateOutput = new stdclass();
$chatCreateOutput->result = 'success';
$chatCreateOutput->method = 'chatcreate';
$chatCreateOutput->users = $privateChatMembers;
$chatCreateOutput->data = $chat;
}
else
{
return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'No such chat, or you are not in the chat.'), 'messageResponsePack');
}
}
if($chat->archiveDate) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->operationNotSupportedOnArchivedChat), 'messageResponsePack');
if($chat->type == 'system' && isset($this->config->xuanxuan->enableSystemConference) && $this->config->xuanxuan->enableSystemConference == 0) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => $this->lang->im->owtIsDisabled), 'messageResponsePack');
$broadcasts = array();
if($isOne2OneChat)
{
$targetUserArray = array_diff($privateChatMembers, array($userID));
if(empty($targetUserArray)) $targetUserArray = array($userID);
$targetUserID = current($targetUserArray);
$targetUser = $this->im->userGetByID($targetUserID);
if($this->im->conferenceIsUserOccupied($targetUserID, $chatID) || $targetUser->status == 'offline')
{
array_push($broadcasts, $this->im->messageCreateBroadcast('createConference', $chat, $privateChatMembers, $userID));
if($targetUser->status != 'offline') array_push($broadcasts, $this->im->messageCreateBroadcast('conferenceInviteeOccupied', $chat, $privateChatMembers, $targetUserID));
$failOutput = new stdclass();
$failOutput->method = 'conferencecreate';
$failOutput->result = 'fail';
$failOutput->users = $privateChatMembers;
$failOutput->message = $targetUser->status == 'offline' ? $this->lang->im->conference->userOffline : $this->lang->im->conference->userBusy;
$failOutput->data = array('actions' => array());
$outputGroup = array_merge(array($failOutput), $broadcasts);
return $this->im->sendOutputGroup($outputGroup);
}
}
$inviteeData = empty($invitee) ? '' : implode(',', $invitee);
$conference = $this->im->conferenceCreate($chatID, $inviteeData, $userID);
if(empty($conference)) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'Create conference fail.'), 'messageResponsePack');
$participants = explode(',', $conference->participants);
if(!in_array((int)$userID, $participants)) $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'Could not join the conference.', 'data' => $chatID), 'messageResponsePack');
if(count($participants) > 1)
{
$conferenceAction = new stdClass();
$conferenceAction->room = $conference->rid;
$conferenceAction->type = 'join';
$conferenceAction->participants = $conference->participants;
$conferenceAction->invitee = $conference->invitee;
$conferenceAction->date = strtotime(helper::now());
$conferenceAction->user = (int)$userID;
$conferenceAction->device = $device;
return $this->im->sendOutput(array('result' => 'success', 'method' => 'conferencejoin', 'users' => $chat->members, 'data' => $conferenceAction), 'conferencejoinResponse');
}
$conferenceData = new stdClass();
$conferenceData->cgid = $chatID;
$conferenceData->room = $conference->rid;
$conferenceData->status = $conference->status;
$conferenceData->openedBy = (int)$userID;
$conferenceData->openedDate = strtotime(helper::now());
$conferenceData->participants = $conference->participants;
$conferenceData->invitee = $conference->invitee;
$conferenceAction = new stdClass();
$conferenceAction->room = $conferenceData->room;
$conferenceAction->type = 'create';
$conferenceAction->participants = $conferenceData->participants;
$conferenceAction->invitee = $conference->invitee;
$conferenceAction->date = $conferenceData->openedDate;
$conferenceAction->user = (int)$userID;
$conferenceAction->device = $device;
$conferenceData->actions = array($conferenceAction);
$output = new stdClass();
$output->method = 'conferencecreate';
$output->users = $chat->members;
$output->result = 'success';
$output->data = $conferenceData;
if($isOne2OneChat && $privateChatMembers[0] == $privateChatMembers[1])
{
$output->users = array();
return $this->im->sendOutputGroup(array($output));
}
$broadcast = empty($invitee) ? $this->im->messageCreateBroadcast('createConference', $chat, $chat->members, $userID) : $this->im->messageCreateBroadcast('createConferenceInvitation', $chat, $invitee, $userID, $invitee, true);
if(!empty($invitee)) foreach($invitee as $user) if($this->im->conferenceIsUserOccupied($user)) array_push($broadcasts, $this->im->messageCreateBroadcast('conferenceInviteeOccupied', $chat, $invitee, $user, $invitee, true));
array_push($broadcasts, $broadcast);
$output = array($output);
if(!empty($broadcasts)) $output = array_merge($output, $broadcasts);
if(isset($chatCreateOutput)) array_unshift($output, $chatCreateOutput);
return $this->im->sendOutputGroup($output);
}
/**
* Invite members to join a conference.
*
* @param string $chatID
* @param int $userID
* @access public
* @return void
*/
public function conferenceInvite($chatID, $newInvitee = array(), $userID = 0, $version = '', $device = 'desktop') {
$this->loadModel('conference');
if(!$this->conference->isEnabled()) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => $this->lang->im->owtIsDisabled), 'messageResponsePack');
$chat = $this->im->chatGetByGidForUser($chatID, $userID);
if(empty($chat)) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'No such chat, or you are not in the chat.'), 'messageResponsePack');
$conference = $this->im->conferenceGetByChatID($chatID);
if(empty($conference)) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'No such conference.'), 'messageResponsePack');
$invitee = $this->im->conferenceAddInvitee($chatID, $newInvitee);
if(empty($invitee)) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'Invitation failed.', 'data' => array('cgid' => $chatID)), 'messageResponsePack');
$this->im->conferenceSaveAction($conference->rid, 'invite', $userID, $device);
$conferenceAction = new stdClass();
$conferenceAction->room = $conference->rid;
$conferenceAction->type = 'invite';
$conferenceAction->invitee = $invitee;
$conferenceAction->participants = $conference->participants;
$conferenceAction->date = strtotime(helper::now());
$conferenceAction->user = (int)$userID;
$conferenceAction->device = $device;
$output = new stdClass();
$output->result = 'success';
$output->users = $chat->members;
$output->data = $conferenceAction;
$output = array($output);
$broadcast = $this->im->messageCreateBroadcast('createConferenceInvitation', $chat, $newInvitee, $userID, $newInvitee, true);
array_push($output, $broadcast);
$invitee = array_filter(explode(',', $invitee));
foreach($invitee as $user) if($this->im->conferenceIsUserOccupied($user, $chatID)) array_push($output, $this->im->messageCreateBroadcast('conferenceInviteeOccupied', $chat, $newInvitee, $user, $newInvitee, true));
return $this->im->sendOutputGroup($output);
}
/**
* Join a conference in a chat.
*
* @param string $chatID
* @param int $userID
* @access public
* @return void
*/
public function conferenceJoin($chatID, $userID, $version = '', $device = 'desktop')
{
$this->loadModel('conference');
if(!$this->conference->isEnabled()) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => $this->lang->im->owtIsDisabled), 'messageResponsePack');
$chat = $this->im->chatGetByGidForUser($chatID, $userID);
if(empty($chat)) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'No such chat, or you are not in the chat.'), 'messageResponsePack');
$conference = $this->im->conferenceGetByChatID($chatID);
if(empty($conference)) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'No such conference.'), 'messageResponsePack');
$participants = $this->im->conferenceAddParticipant($chatID, $userID);
if(empty($participants)) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'Could not join the conference.', 'data' => array('cgid' => $chatID)), 'messageResponsePack');
$this->im->conferenceSaveAction($conference->rid, 'join', $userID, $device);
$conferenceAction = new stdClass();
$conferenceAction->room = $conference->rid;
$conferenceAction->type = 'join';
$conferenceAction->participants = $participants;
$conferenceAction->invitee = $conference->invitee;
$conferenceAction->date = strtotime(helper::now());
$conferenceAction->user = (int)$userID;
$conferenceAction->device = $device;
/* Include all last publish actions of participants */
$publishActions = $this->im->conferenceGetActions($conference, 'publish');
$publishActionsMap = array();
foreach($publishActions as $action)
{
if($action->user == $userID) continue;
if(isset($publishActionsMap[$action->user]) && $publishActionsMap[$action->user]->id > $action->id) continue;
$publishActionsMap[$action->user] = $action;
}
$conferenceAction->actions = array_values($publishActionsMap);
return $this->im->sendOutput(array('result' => 'success', 'users' => $chat->members, 'data' => $conferenceAction), 'conferencejoinResponse');
}
/**
* Leave a conference in a chat.
*
* @param string $chatID
* @param int $userID
* @access public
* @return void
*/
public function conferenceLeave($chatID, $userID, $version = '', $device = 'desktop')
{
$chat = $this->im->chatGetByGidForUser($chatID, $userID);
if(empty($chat)) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'No such chat, or you are not in the chat.'), 'messageResponsePack');
$conference = $this->im->conferenceGetByChatID($chatID);
if(empty($conference)) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'No such conference.'), 'messageResponsePack');
if($conference->status == 'closed') $alreadyClosed = true;
$participants = $this->im->conferenceRemoveParticipant($chatID, $userID);
$this->im->conferenceSaveAction($conference->rid, 'leave', $userID);
$conferenceAction = new stdClass();
$conferenceAction->room = $conference->rid;
$conferenceAction->type = 'leave';
$conferenceAction->participants = $participants;
$conferenceAction->invitee = $conference->invitee;
$conferenceAction->date = strtotime(helper::now());
$conferenceAction->user = (int)$userID;
$conferenceAction->device = $device;
$participants = explode(',', $participants);
$participants = array_filter($participants);
$privateChatMembers = explode('&', $chatID);
$isOne2OneChat = (count($privateChatMembers) == 2);
if(!isset($alreadyClosed) && (empty($participants) || count($participants) == 0) && !($isOne2OneChat && $privateChatMembers[0] == $privateChatMembers[1]))
{
$this->im->conferenceClose($chatID, $userID);
$conferenceAction->type = 'close';
$conferenceAction->participants = array();
$output = new stdClass();
$output->method = 'conferenceclose';
$output->users = $chat->members;
$output->result = 'success';
$output->data = $conferenceAction;
$broadcast = $this->im->messageCreateBroadcast('closeConference', $chat, $chat->members, $userID, array(), true);
if($broadcast) $output = array($output, $broadcast);
return $this->im->sendOutputGroup($output);
}
return $this->im->sendOutput(array('result' => 'success', 'users' => $chat->members, 'data' => $conferenceAction), 'conferenceleaveResponse');
}
/**
* Close a conference in a chat.
*
* @param string $chatID
* @param int $userID
* @access public
* @return void
*/
public function conferenceClose($chatID, $userID, $version = '', $device = 'desktop')
{
$chat = $this->im->chatGetByGidForUser($chatID, $userID);
if(empty($chat)) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'No such chat, or you are not in the chat.'), 'messageResponsePack');
$conference = $this->im->conferenceGetByChatID($chatID);
if(empty($conference)) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'No such conference.'), 'messageResponsePack');
$this->im->conferenceClose($chatID, $userID);
$conferenceAction = new stdClass();
$conferenceAction->room = $conference->rid;
$conferenceAction->type = 'close';
$conferenceAction->participants = '';
$conferenceAction->invitee = $conference->invitee;
$conferenceAction->date = strtotime(helper::now());
$conferenceAction->user = (int)$userID;
$conferenceAction->device = $device;
$output = new stdClass();
$output->method = 'conferenceclose';
$output->users = $chat->members;
$output->result = 'success';
$output->data = $conferenceAction;
$privateChatMembers = explode('&', $chatID);
$isOne2OneChat = (count($privateChatMembers) == 2);
if($isOne2OneChat && $privateChatMembers[0] == $privateChatMembers[1])
{
$output->users = array();
return $this->im->sendOutputGroup(array($output));
}
$broadcast = $this->im->messageCreateBroadcast('closeConference', $chat, $chat->members, $userID, array(), true);
if($broadcast) $output = array($output, $broadcast);
return $this->im->sendOutputGroup($output);
}
/**
* Sync action of a conference in a chat.
*
* @param string $chatID
* @param string $action publish
* @param string $data Action data
* @param int $userID
* @param int $device
* @access public
* @return void
*/
public function conferenceSyncAction($chatID, $action, $data, $userID, $version = '', $device = 'desktop')
{
$chat = $this->im->chatGetByGidForUser($chatID, $userID);
if(empty($chat)) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'No such chat, or you are not in the chat.'), 'messageResponsePack');
$conference = $this->im->conferenceGetByChatID($chatID);
if(empty($conference)) return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'No such conference.'), 'messageResponsePack');
if($action != 'publish')
{
return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'Illegal action.'), 'messageResponsePack');
}
$conferenceAction = $this->im->conferenceSaveAction($conference->rid, $action, $userID, $device, $data);
$output = new stdClass();
$output->method = 'conferencesyncaction';
$output->users = $chat->members; // TODO: only send to members in conference
$output->result = 'success';
$output->data = $conferenceAction;
return $this->im->sendOutput($output, 'conferencesyncactionResponse');
}
/**
* Get extensions.
*
* @param int $userID
* @access public
* @return void
*/
public function extensionGetList($userID = 0)
{
$output = new stdclass();
$output->result = 'success';
$output->data = $this->im->getExtensionList($userID);
$output->users = array($userID);
return $this->im->sendOutput($output, 'extensiongetlistResponse');
}
/**
* Get latest notification and offline user.
* @param array $offline
* @param array $sendfail
* @access public
* @return void
*/
public function syncNotifications($offline = array(), $sendfail = array())
{
if(!empty($offline)) $this->im->userSetOffline($offline);
if(!empty($sendfail)) $this->im->messageSendFailures($sendfail);
/* Push notifications to mobile clients. */
$output = new stdClass();
if(dao::isError())
{
$output->result = 'fail';
$output->message = 'Get notify fail.';
}
else
{
ini_set('memory_limit', '256M'); // Set memory limit to avoid OOMs.
$output->result = 'success';
$output->data = $this->im->messageGetNotifyList();
}
return $this->app->output($this->app->encrypt($output));
}
/**
* Check user change, and update their pinyin of realname.
*
* @access public
* @return void
*/
public function syncUsers()
{
$this->im->updateLastPoll();
$changedUsers = $this->im->userHasChanges();
if(!empty($changedUsers))
{
$this->im->userReindexPinyin($changedUsers);
$changedUsers = $this->im->userGetList('', $changedUsers, false);
}
$output = new stdClass();
$output->result = 'success';
$output->data = empty($changedUsers) ? array() : $changedUsers;
return $this->app->output($this->app->encrypt($output));
}
/**
* Check for dept changes, and provide sysgetdepts output if needed.
*
* @access public
* @return void
*/
public function syncDepts()
{
$deptChanges = $this->im->userHasChanges('dept');
if(empty($deptChanges)) return $this->app->output($this->app->encrypt(array('result' => 'success', 'data' => '')));
$getDeptsOutput = $this->fetch('im', 'sysGetDepts', array(0));
$getDeptsOutput = explode("\n", $getDeptsOutput);
$getDeptsOutput = $getDeptsOutput[count($getDeptsOutput) - 1];
$getDeptsOutput = addslashes($getDeptsOutput); // Otherwise Go might not be able to parse such JSON.
return $this->app->output($this->app->encrypt(array('result' => 'success', 'data' => $getDeptsOutput)));
}
/**
* Get config settings for XXD.
*
* @access public
* @return void
*/
public function syncConfig()
{
$output = new stdclass();
$output->module = 'im';
$output->method = 'syncConfig';
$output->result = 'success';
$output->data = new stdclass();
$output->data->ip = $this->config->xuanxuan->ip;
$output->data->chatPort = $this->config->xuanxuan->chatPort;
$output->data->commonPort = $this->config->xuanxuan->commonPort;
$output->data->https = $this->config->xuanxuan->https;
$output->data->pollingInterval = $this->config->xuanxuan->pollingInterval;
$output->data->uploadFileSize = $this->config->xuanxuan->uploadFileSize;
if(isset($this->config->xuanxuan->fileEncryptionKey)) $output->data->fileKey = $this->config->xuanxuan->fileEncryptionKey;
return $this->app->output($this->app->encrypt($output));
}
/**
* Upload file.
*
* @param string $fileName
* @param string $path
* @param int $size
* @param int $time
* @param string $gid
* @param int $userID
* @access public
* @return void
*/
public function fileUpload($fileName = '', $path = '', $size = 0, $time = 0, $gid = '', $userID = 0)
{
$chat = $this->im->chat->getByGid($gid, true);
if(!$chat)
{
$one2oneMembers = explode('&', $gid);
if(count($one2oneMembers) !== 2) return $this->app->output($this->app->encrypt(array('result' => 'fail', 'message' => $this->lang->im->notExist)));
$chat = (object)array('id' => 0, 'members' => array($userID));
}
$users = $this->im->userGetList($status = 'online', $chat->members);
$fileID = $this->im->uploadFile($fileName, $path, $size, $time, $userID, $users, $chat);
if(dao::isError()) return $this->app->output($this->app->encrypt(array('result' => 'fail', 'message' => 'Upload file fail.')));
$output = new stdclass();
$output->result = 'success';
$output->users = array_keys($users);
$output->data = $fileID;
return $this->app->output($this->app->encrypt($output));
}
/**
* Create, edit or delte todo
* @param object $todo
* @param int $userID
* @access public
* @return void
*/
public function todoUpsert($todo, $userID = 0)
{
$user = $this->im->userGetByID($userID);
if(is_object($todo))
{
if(isset($todo->id))
{
if($todo->delete)
{
$todo = $this->loadModel('todo')->getById($todo->id);
if($todo->account != $user->account)
{
return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'Cannot delete todo item witch not yours.', 'data' => $todo), 'messageResponsePack');
}
else
{
$this->dao->delete()->from(TABLE_TODO)->where('id')->eq($todo->id)->exec();
if(dao::isError())
{
return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => dao::getError()), 'messageResponsePack');
}
else
{
$this->loadModel('action')->create('todo', $todo->id, 'deleted', 'success', '', '', $user->account);
$output = new stdClass();
$output->result = 'success';
$output->users = array($userID);
$output->data = $todo;
return $this->im->sendOutput($output, 'todoupsertResponse');
}
}
}
else
{
$_POST = (array)$todo;
$changes = $this->loadModel('todo')->update($todo->id);
if(dao::isError())
{
return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => dao::getError()), 'messageResponsePack');
}
else
{
$actionID = $this->loadModel('action')->create('todo', $todo->id, 'edit', 'success', '', '', $user->account);
$this->action->logHistory($actionID, $changes);
$output = new stdClass();
$output->result = 'success';
$output->users = array($userID);
$output->data = $todo;
return $this->im->sendOutput($output, 'todoupsertResponse');
}
}
}
else
{
$_POST = (array)$todo;
$todoID = $this->loadModel('todo')->create($todo->date, $user->account);
if(dao::isError())
{
return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => dao::getError()), 'messageResponsePack');
}
else
{
$this->loadModel('action')->create('todo', $todoID, 'created', 'success', '', '', $user->account);
$todo->id = $todoID;
$output = new stdClass();
$output->result = 'success';
$output->users = array($userID);
$output->data = $todo;
return $this->im->sendOutput($output, 'todoupsertResponse');
}
}
}
else
{
return $this->im->sendOutput(array('result' => 'fail', 'users' => $userID, 'message' => 'The todo param is not an object.'), 'messageResponsePack');
}
}
/**
* Get todo list.
*
* @param string $mode
* @param string $orderBy
* @param string $status
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @param int $userID
* @access public
* @return void
*/
public function todoGetList($mode = 'all', $status = 'unclosed', $orderBy = 'date_asc', $recTotal = 0, $recPerPage = 20, $pageID = 1, $userID = 0)
{
$user = $this->im->userGetByID($userID);
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
if($mode == 'future')
{
$todos = $this->loadModel('todo')->getList('self', $user->account, 'future', empty($status) ? 'unclosed' : $status, $orderBy, $pager);
}
else if($mode == 'all')
{
$todos = $this->loadModel('todo')->getList('self', $user->account, 'all', empty($status) ? 'all' : $status, $orderBy, $pager);
}
else if($mode == 'undone')
{
$todos = $this->loadModel('todo')->getList('self', $user->account, 'before', empty($status) ? 'undone' : $status, $orderBy, $pager);
}
else
{
$todos = $this->loadModel('todo')->getList($mode, $user->account, 'all', empty($status) ? 'unclosed' : $status, $orderBy, $pager);
}
$output = new stdclass();
$output->data = $todos;
$output->result = 'success';
$output->users = array($userID);
return $this->app->output($this->app->encrypt($output));
}
/**
* Get chat group pairs.
*
* @access public
* @return void
*/
public function getGroupChats()
{
$response = array();
$response['result'] = 'success';
$groupPairs = $this->im->chatGetGroupPairs();
if(dao::isError())
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
}
else
{
$response['data'] = $groupPairs;
}
die(json_encode($response));
}
/**
* Get all user pairs or users of one chat group.
*
* @param string $gid
* @access public
* @return void
*/
public function getChatUsers($gid = '')
{
$response = array();
$response['result'] = 'success';
$userPairs = $this->im->chatGetUserPairs($gid);
if(dao::isError())
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
}
else
{
$response['data'] = $userPairs;
}
die(json_encode($response));
}
/**
* Send notification to users' notification center.
*
* @access public
* @return void
*/
public function sendNotification()
{
/* Parse input data. */
$input = file_get_contents("php://input");
$data = json_decode($input);
$response = array('result' => 'success', 'message' => '');
if(empty($data->users))
{
$response['result'] = 'fail';
$response['message'] = $this->lang->im->notify->setUserList;
die(json_encode($response));
}
if(empty($data->sender))
{
$response['result'] = 'fail';
$response['message'] = $this->lang->im->notify->setSender;
die(json_encode($response));
}
if(empty($data->title))
{
$response['result'] = 'fail';
$response['message'] = $this->lang->im->notify->setTitle;
die(json_encode($response));
}
$users = $data->users;
$sender = $data->sender;
$title = $data->title;
$subtitle = $data->subtitle ?: '';
$content = $data->content ?: '';
$contentType = $data->contentType ?: 'text';
$url = $data->url ?: '';
$actions = $data->actions ?: array();
$result = $this->im->messageCreateNotify($users, $title, $subtitle, $content, $contentType, $url, $actions, $sender);
if(!$result)
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
}
die(json_encode($response));
}
/**
* Send notification into chat.
*
* @access public
* @return void
*/
public function sendChatMessage()
{
/* Parse input data. */
$input = file_get_contents("php://input");
$data = json_decode($input);
$response = array('result' => 'success', 'message' => '');
if(empty($data->gid))
{
$response['result'] = 'fail';
$response['message'] = $this->lang->im->notify->setGroup;
die(json_encode($response));
}
if(empty($data->sender))
{
$response['result'] = 'fail';
$response['message'] = $this->lang->im->notify->setSender;
die(json_encode($response));
}
if(empty($data->title))
{
$response['result'] = 'fail';
$response['message'] = $this->lang->im->notify->setTitle;
die(json_encode($response));
}
$gid = $data->gid;
$sender = $data->sender;
$title = $data->title;
$subtitle = $data->subtitle ?: '';
$content = $data->content ?: '';
$contentType = $data->contentType ?: 'text';
$url = $data->url ?: '';
$actions = $data->actions ?: array();
$result = $this->im->messageCreateNotify($gid, $title, $subtitle, $content, $contentType, $url, $actions, $sender);
if(!$result)
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
}
die(json_encode($response));
}
/**
* Sync foreign user data into xuan database.
*
* @access public
* @return void
*/
public function syncUsersData()
{
/* Parse input data, array of users. */
$input = file_get_contents("php://input");
$data = json_decode($input);
$this->loadModel('user');
/* Get existing user list. */
$existingAccounts = array_map(function($u) {return $u->account;}, $this->user->getList($dept = null, $mode = 'all'));
$response = array('result' => 'success', 'message' => '', 'fails' => array());
/* Get departments mapping configuration. */
$deptsMapping = isset($this->config->im->depts) ? json_decode($this->config->im->depts->mapping) : new stdClass();
foreach($data as $user)
{
/* Try to find dept id in mapping configuration and replace. */
if(isset($user->dept) && isset($deptsMapping->{$user->dept})) $user->dept = $deptsMapping->{$user->dept};
if(in_array($user->account, $existingAccounts))
{
/* Update user with new data. */
$result = $this->user->apiUpdate($user);
}
else
{
/* Create user with the data. */
$result = $this->user->apiCreate($user);
}
/* Push account to fails on failure. */
if(!$result) $response['fails'][] = $user->account;
}
if(!empty($response['fails']))
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
}
else
{
unset($response['fails']);
unset($response['message']);
}
die(json_encode($response));
}
/**
* Sync foreign department data into xuan database.
*
* @access public
* @return void
*/
public function syncDeptsData()
{
/* Parse post data, array of depts. */
$input = file_get_contents("php://input");
$data = json_decode($input);
$response = array('result' => 'success', 'message' => '', 'fails' => array());
/* Fetch depts mapping table. */
$mapping = isset($this->config->im->depts) ? json_decode($this->config->im->depts->mapping) : new stdClass();
$this->loadModel('dept');
foreach($data as $dept)
{
/* Set type as dept. */
$dept->type = 'dept';
/* If parent is set, use parent's mapping id. */
if($dept->parent != 0) $dept->parent = $mapping->{$dept->parent};
/* Create or update a dept and get its record id. */
$deptRecordID = $this->dept->apiUpsertDept($dept, isset($mapping->{$dept->id}) ? $mapping->{$dept->id} : null);
/* Break on error. */
if(!$deptRecordID)
{
$response['fails'][] = $dept->id;
continue;
}
/* Store acutal record id in $mapping. */
$mapping->{$dept->id} = $deptRecordID;
}
/* Save mapping configuration. */
$this->loadModel('setting')->setItem('system.im.depts.mapping', json_encode($mapping));
if(!empty($response['fails']))
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
}
else
{
unset($response['fails']);
unset($response['message']);
}
die(json_encode($response));
}
/**
* Debug xuanxuan.
*
* @param string $source
* @access public
* @return void
*/
public function debug($source = 'x_php')
{
if(RUN_MODE != 'front') return $this->app->output('Access Denied');
$this->view->title = $this->lang->im->debug;
$this->view->source = $source;
$this->view->xxdStatus = $this->im->getXxdStatus();
$this->view->checkXXBConfig = $this->im->checkXXBConfig();
$this->display();
}
/**
* Read content of log file and display.
*
* @access public
* @return void
*/
public function showLog()
{
$logFile = $this->app->getLogRoot() . 'xuanxuan.' . date('Ymd') . '.log.php';
if(!file_exists($logFile)) $this->send(array('result' => 'fail', 'message' => $this->lang->im->noLogFile));
if(!function_exists('fopen')) $this->send(array('result' => 'fail', 'message' => $this->lang->im->noFopen));
$line = $this->config->im->logLine;
$pos = -2;
$eof = '';
$log = '';
$fp = fopen($logFile, 'r');
while($line > 0)
{
while($eof != "\n")
{
if(!fseek($fp, $pos, SEEK_END))
{
$eof = fgetc($fp);
$pos--;
}
else
{
break;
}
}
$log .= fgets($fp) . '<br>';
$eof = '';
$line--;
}
$this->send(array('result' => 'success', 'logs' => $log));
}
/**
* Update last polling time record.
*
* @access public
* @return void
*/
public function updateLastPoll()
{
$this->im->updateLastPoll();
return $this->im->sendOutput(array('result' => 'success'));
}
/**
* Check for users that changed their password but did not re-login.
* TODO: Remove this function on a later release.
*
* @access public
* @deprecated 5.4
* @return void
*/
public function checkPasswordChanges()
{
return $this->getKickList();
}
/**
* Run nightly maintenance jobs.
*
* @access public
* @return void
*/
public function maintenance()
{
$output = new stdClass();
$output->module = 'im';
$output->method = 'maintenance';
$output->result = 'success';
set_time_limit(0);
ini_set('memory_limit', '2048M');
/* Reindex users' pinyin of realname. */
$this->im->userReindexPinyin();
/* Run message table partition job. */
$partitionMark = $this->im->messageMarkOngoingPartition(true);
if($partitionMark)
{
if($this->im->messageNeedPartition()) $this->im->messagePartitionTable();
$this->im->messageMarkOngoingPartition(false);
}
/* TODO: revive this in 6.3. */
// $shouldPruneChats = $this->loadModel('setting')->getItem("owner=system&module=common&section=xuanxuan&key=enableCleanDismissGroup");
// if(isset($shouldPruneChats) && $shouldPruneChats == 'on') $this->im->chatPruneExpired();
return $this->app->output($this->app->encrypt($output));
}
/**
* Donwload XXD package.
*
* @param string xxd package name.
* @access public
* @return void
*/
public function downloadXxdPackage($xxdFileName)
{
set_time_limit(0);
$version = $this->config->xuanxuan->version;
$xxdDirectory = $this->app->tmpRoot . 'xxd' . DS . $version;
$xxdFile = fopen($xxdDirectory . DS . $xxdFileName, 'rb');
Header("Content-type: application/octet-stream");
Header("Accept-Ranges: bytes");
Header("Accept-Length: " . filesize ($xxdDirectory . DS . $xxdFileName));
Header("Content-Disposition: attachment; filename=" . $xxdFileName);
echo fread($xxdFile, filesize($xxdDirectory . DS . $xxdFileName));
fclose($xxdFile);
}
/**
* Authorize and redirect user to url.
*
* @param string $account
* @param string $token
* @param string $device
* @param string $url
* @access public
* @return void
*/
public function authorize($account = '', $token = '', $device = '', $url = '')
{
if(!empty($url)) $url = str_replace('_', $this->config->requestFix, $url);
if(empty($account) || empty($token)) die('Invalid params. Please provide account, token and url.');
$user = $this->im->userIdentifyWithToken($account, $token, $device);
if(!$user || is_string($user)) die('Invalid token.');
if(empty($url)) die('Authorized, but no url to redirect to.');
$user = $this->loadModel('user')->getByAccount($account);
$user = $this->user->login($user);
$url .= $this->config->requestType == 'GET' ? '&' : '?';
$url .= "{$this->config->sessionVar}={$this->app->sessionID}";
header("Location: $url", true, 307);
}
/**
* Get user list to kick, currently kicks users with password changes, deletions, and forbiddance.
*
* @access public
* @return void
*/
public function getKickList()
{
$output = new stdclass();
$output->module = 'im';
$output->method = 'getkicklist';
$output->result = 'success';
$output->data = new stdclass();
$output->data->kickedChangePwd = array();
$output->data->kickedDeleted = $this->im->userGetOnlineDeleted();
$output->data->kickedForbided = $this->im->userGetOnlineForbidden();
return $this->app->output($this->app->encrypt($output));
}
/**
* Change a chat.
*
* @param string $gid
* @param objcet $config {"public":true,"adminInvite":true,"commiters":""}
* @param int $userID
* @access public
* @return void
*/
public function chatSetConfig($gid = '', $config = array(), $userID = 0)
{
$chat = $this->im->chat->getByGid($gid);
if(!$chat) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notExist), 'messageResponsePack');
if($chat->type != 'group' && $chat->type != 'system') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupChat), 'messageResponsePack');
if($chat->archiveDate)
{
$chat = $this->im->chat->getByGid($gid, true);
$output = new stdclass();
$output->result = 'success';
$output->users = array($userID);
$output->data = $chat;
return $this->im->sendOutput($output, 'chatsetconfigResponse');
}
$chatID = $chat->id;
if(isset($config->public))
{
$chat->public = $config->public ? '1' : '0';
}
if(isset($config->committers))
{
if($chat->type != 'group' && $chat->type != 'system') return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notGroupChat), 'messageResponsePack');
$chat->committers = $config->committers;
}
if(isset($config->adminInvite))
{
$chat->adminInvite = $config->adminInvite ? '1' : '0';
}
if(isset($config->avatar))
{
$chat->avatar = $config->avatar;
}
$chat = $this->im->chatUpdate($chat, $userID);
if(dao::isError())
{
$this->im->chatAddAction($chatID, 'chatSetConfig', $userID, 'fail');
return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Set chat config fail.'), 'messageResponsePack');
}
$this->im->chatAddAction($chatID, 'chatSetConfig', $userID, 'success');
$users = $this->im->userGetList($status = 'online', $chat->members);
$output = new stdclass();
$output->result = 'success';
$output->users = array_keys($users);
$output->data = $chat;
return $this->im->sendOutput($output, 'chatsetconfigResponse');
}
/**
* search chats with super admin.
*
* @param string $searchField
* @param object $pager
* @param string $orderBy
* @param boolean $onlyGetChats
* @param int $userID
* @access public
* @return array
*/
public function chatSearch($searchField='', $pager = null, $orderBy = '', $onlyGetChats = false, $userID = 0)
{
$account = $this->dao->select('account')->from(TABLE_USER)->where('id')->eq($userID)->fetch('account');
$sysAdmins = $this->dao->select('admins')->from(TABLE_COMPANY)->where('id')->eq($this->app->company->id)->fetch('admins');
$sysAdminArray = explode(',', $sysAdmins);
$super = in_array($account, $sysAdminArray) ? 'super' : '';
if($super != 'super')
{
return $this->im->sendOutput(array('result' => 'success', 'data' => array()));
}
$output = new stdclass();
$output->result = 'success';
$output->users = array($userID);
if($onlyGetChats)
{
$chatList = $this->im->chatAdminGetChatGroups();
$output->data = $this->im->chatFormat($chatList);
return $this->im->sendOutput($output, 'chatgetpubliclistResponse');
}
else
{
if(empty($pager)) $pager = new stdclass();
if(empty($orderBy)) $orderBy = 'createdDate_desc';
if(!isset($pager->pageID)) $pager->pageID = 1;
if(!isset($pager->recPerPage)) $pager->recPerPage = 10;
if(!isset($pager->recTotal)) $pager->recTotal = 0;
$this->app->loadClass('pager', $static = true);
$pager = new pager($pager->recTotal, $pager->recPerPage, $pager->pageID);
$chatList = $this->im->chatSearch($searchField, $pager, $orderBy);
$output->data = $chatList;
$output->pager = new stdclass();
$output->pager->recPerPage = $pager->recPerPage;
$output->pager->pageID = $pager->pageID;
$output->pager->recTotal = $pager->recTotal;
}
return $this->im->sendOutput($output, 'chatsearchResponse');
}
/**
* Set chat avatar.
*
* @param string $gid
* @param object $avatar
* @param int $userID
* @access public
* @return void
*/
public function chatSetAvatar($gid, $avatar = null, $userID = 0)
{
$chat = $this->im->chat->getByGid($gid);
if(!$chat) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notExist), 'messageResponsePack');
if($chat->archiveDate)
{
$output = new stdclass();
$output->result = 'success';
$output->users = array($userID);
$output->data = $chat;
return $this->im->sendOutput($output, 'chatsetavatarResponse');
}
if(!$this->im->chatIsAdmin($chat, $userID)) return $this->im->sendOutput(array('result' => 'fail', 'message' => $this->lang->im->notAdmin), 'messageResponsePack');
if($avatar->type == 'image')
{
$file = $this->loadModel('file')->getById($avatar->data->imgId);
$avatar->data->imgUrl = $file->webPath;
unset($avatar->data->imgId);
}
/* Sanitize input. */
if($avatar->type == 'text') $avatar->data->customText = strip_tags($avatar->data->customText);
$avatarEncoded = json_encode($avatar);
$chat = $this->im->chatUpdateAvatar($gid, $avatarEncoded);
if(dao::isError())
{
$this->im->chatAddAction($gid, 'chatSetAvatar', $userID, 'fail');
return $this->im->sendOutput(array('result' => 'fail', 'message' => 'Set chat avatar fail.'), 'messageResponsePack');
}
$this->im->chatAddAction($gid, 'chatSetAvatar', $userID, 'success');
if($avatar->type == 'image') $avatar->data->imgUrl = $this->loadModel('im')->getServer() . $avatar->data->imgUrl;
$chat->avatar = $avatar;
$users = $this->im->userGetList($status = 'online', $chat->members);
$output = new stdclass();
$output->result = 'success';
$output->users = array_keys($users);
$output->data = $chat;
return $this->im->sendOutput($output, 'chatsetavatarResponse');
}
}