TencentImGroupService.php 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <?php
  2. namespace App\Services;
  3. use App\Exceptions\TencentImException;
  4. use App\Exceptions\TencentImGroupException;
  5. use App\Models\TencentImGroup;
  6. use App\Traits\TencentIm;
  7. use Carbon\Carbon;
  8. use Illuminate\Support\Facades\DB;
  9. use Illuminate\Support\Facades\Log;
  10. class TencentImGroupService
  11. {
  12. use TencentIm;
  13. public const TENCENT_REST_APIS = [
  14. 'createGroup' => 'v4/group_open_http_svc/create_group', // 创建群组 支持同时创建多个
  15. 'getGroupList' => 'v4/group_open_http_svc/get_appid_group_list', // 获取app中所有群组
  16. ];
  17. public const IM_GROUP_RAW_TYPE_PUBLIC = 'Public'; // 陌生人社交群
  18. public const IM_GROUP_RAW_TYPE_Private = 'Private'; // 即 Work,好友工作群
  19. public const IM_GROUP_RAW_TYPE_ChatRoom = 'ChatRoom'; // 即 Meeting,会议群
  20. public const IM_GROUP_RAW_TYPE_AVChatRoom = 'AVChatRoom'; // 直播群
  21. public const IM_GROUP_RAW_TYPE_TIPS = [
  22. self::IM_GROUP_RAW_TYPE_PUBLIC => '陌生人交友群',
  23. self::IM_GROUP_RAW_TYPE_Private => '好友工作群',
  24. self::IM_GROUP_RAW_TYPE_ChatRoom => '会议群',
  25. self::IM_GROUP_RAW_TYPE_AVChatRoom => '直播群',
  26. ];
  27. /**
  28. * 获取所有 APP 中的群组.
  29. *
  30. * @return \Psr\Http\Message\ResponseInterface
  31. *
  32. * @throws \App\Exceptions\TencentImAccountException
  33. * @throws \App\Exceptions\TencentImException
  34. * @throws \GuzzleHttp\Exception\GuzzleException
  35. */
  36. public function getGroupList(int $limit = 10000, int $next = 0)
  37. {
  38. $this->restApiName = self::TENCENT_REST_APIS['getGroupList'];
  39. $baseApiHost = $this->getTencentImRestApiBaseHost();
  40. $params = [
  41. 'Limit' => $limit,
  42. 'Next' => $next,
  43. ];
  44. $apiResult = $this->requestApi($baseApiHost, $params);
  45. self::verifyApiResult($apiResult);
  46. return $apiResult;
  47. }
  48. /**
  49. * 验证类型是否存在.
  50. *
  51. * @return bool
  52. *
  53. * @throws TencentImGroupException
  54. */
  55. public static function verifyImGroupType(string $groupType)
  56. {
  57. if (!array_key_exists($groupType, TencentImGroup::IM_GROUP_RAW_TYPE_TIPS)) {
  58. throw new TencentImGroupException('群类型不存在');
  59. }
  60. return true;
  61. }
  62. /**
  63. * 验证当日建群上限,并返回当前可以添加的数量.
  64. *
  65. * @return int
  66. *
  67. * @throws TencentImGroupException
  68. */
  69. public static function verifyToDayCreateCount()
  70. {
  71. if (TencentImGroup::getToDayCreateCount() >= TencentImGroup::IM_GROUP_CREATE_DAY_MAX) {
  72. throw new TencentImGroupException('单日新建群组上限为: ' . TencentImGroup::IM_GROUP_CREATE_DAY_MAX);
  73. }
  74. return TencentImGroup::IM_GROUP_CREATE_DAY_MAX - TencentImGroup::getToDayCreateCount();
  75. }
  76. /**
  77. * 验证当月建群上限,并返回可以添加的数量.
  78. *
  79. * @return int
  80. *
  81. * @throws TencentImGroupException
  82. */
  83. public static function verifyMonthCreateCount()
  84. {
  85. if (TencentImGroup::getMonthCreateCount() >= TencentImGroup::IM_GROUP_CREATE_MONTH_MAX) {
  86. throw new TencentImGroupException('单月新建群组上限为: ' . TencentImGroup::IM_GROUP_CREATE_MONTH_MAX);
  87. }
  88. return TencentImGroup::IM_GROUP_CREATE_MONTH_MAX - TencentImGroup::getMonthCreateCount();
  89. }
  90. /**
  91. * 验证是否可以添加群.
  92. *
  93. * @throws TencentImGroupException
  94. */
  95. public static function verifyIsCreateGroup(int $groupCount)
  96. {
  97. // 验证单次最低
  98. if ($groupCount < TencentImGroup::IM_GROUP_ONCE_CREATE_MIN) {
  99. throw new TencentImGroupException('单次添加最低' . TencentImGroup::IM_GROUP_ONCE_CREATE_MIN . ' 个群');
  100. }
  101. // 验证单次最多
  102. if ($groupCount > TencentImGroup::IM_GROUP_ONCE_CREATE_MAX) {
  103. throw new TencentImGroupException('单次添加最多' . TencentImGroup::IM_GROUP_ONCE_CREATE_MAX . ' 个群');
  104. }
  105. // 验证当天添加群数量
  106. $canToDayCount = self::verifyToDayCreateCount();
  107. // 验证当月添加上限
  108. $canMonthCount = self::verifyMonthCreateCount();
  109. if ($groupCount > $canToDayCount) {
  110. throw new TencentImGroupException('当前创建数量超过日上限,当日还可创建 ' . $canToDayCount . '个');
  111. }
  112. if ($groupCount > $canMonthCount) {
  113. throw new TencentImGroupException('当前创建数量超过月上限,当月还可创建 ' . $canMonthCount . '个');
  114. }
  115. return true;
  116. }
  117. /**
  118. * @throws TencentImGroupException
  119. * @throws \App\Exceptions\TencentImException
  120. */
  121. public function createGroups(int $groupCount, string $groupType = TencentImGroup::DEFAULT_IM_RAW_GROUP_TYPE)
  122. {
  123. try {
  124. // 验证群类型是否存在
  125. self::verifyImGroupType($groupType);
  126. // 是否可以创建群
  127. self::verifyIsCreateGroup($groupCount);
  128. DB::beginTransaction();
  129. $this->restApiName = self::TENCENT_REST_APIS['createGroup'];
  130. $baseApiHost = $this->getTencentImRestApiBaseHost();
  131. // TODO 做单点登录,避免并发
  132. $groupStartIndex = TencentImGroup::getGroupIndex();
  133. $groupEndIndex = $groupStartIndex + $groupCount;
  134. for ($i = $groupStartIndex; $i < $groupEndIndex; $i++) {
  135. $item = [
  136. // TODO 新建群默认群主为APP管理员
  137. 'Owner_Account' => config('im.identifier'),
  138. 'Type' => TencentImGroup::IM_GROUP_RAW_TYPE_ChatRoom,
  139. 'Name' => (string) $i,
  140. ];
  141. $apiResult = $this->requestApi($baseApiHost, $item);
  142. self::verifyApiResult($apiResult);
  143. $item['GroupId'] = $apiResult['GroupId'];
  144. $item['groupIndex'] = $i;
  145. $params[] = $item;
  146. }
  147. unset($item);
  148. if (count($params) != $groupCount) {
  149. throw new TencentImGroupException('添加群组失败!');
  150. }
  151. $params = array_map(function ($value) {
  152. return [
  153. 'group_name' => $value['Name'],
  154. 'im_group_raw_id' => $value['GroupId'] ?? $value['groupIndex'],
  155. 'group_owner_user_id' => null,
  156. 'im_group_owner_raw_user_id' => $value['Owner_Account'],
  157. 'group_type' => null,
  158. 'im_group_raw_type' => $value['Type'],
  159. 'is_use' => TencentImGroup::UN_USE,
  160. 'bind_system_im_group_id' => null,
  161. 'group_index' => $value['groupIndex'] ?? 0,
  162. 'created_at' => Carbon::now(),
  163. 'updated_at' => Carbon::now(),
  164. ];
  165. }, $params);
  166. if (!TencentImGroup::insert($params)) {
  167. Log::log(date('Y-m-d H:i:s', time()) . '创建IM群组,写入系统记录失败', $params);
  168. throw new TencentImGroupException('创建IM群写入系统记录失败,请联系管理员检查');
  169. }
  170. DB::commit();
  171. return true;
  172. } catch (TencentImGroupException $e) {
  173. DB::rollBack();
  174. return ['error' => $e->getMessage()];
  175. } catch (TencentImException $e) {
  176. DB::rollBack();
  177. dd($e);
  178. return ['error' => $e->getMessage()];
  179. } catch (\Exception $e) {
  180. DB::rollBack();
  181. dd($e);
  182. return ['error' => $e->getMessage()];
  183. }
  184. }
  185. public function createGroup(array $createData)
  186. {
  187. $this->restApiName = self::TENCENT_REST_APIS['createGroup'];
  188. $baseApiHost = $this->getTencentImRestApiBaseHost();
  189. // TODO 做单点登录,避免并发
  190. $params = [
  191. // TODO 新建群默认群主为APP管理员
  192. 'Owner_Account' => config('im.identifier'),
  193. 'Type' => TencentImGroup::IM_GROUP_RAW_TYPE_ChatRoom,
  194. 'Name' => TencentImGroup::getGroupIndex(),
  195. ];
  196. $apiResult = $this->requestApi($baseApiHost, $params);
  197. dd($apiResult);
  198. }
  199. /**
  200. * 构建添加群数组.
  201. */
  202. private function generateCreateGroupData(int $groupCount)
  203. {
  204. $groupStartIndex = TencentImGroup::getGroupIndex();
  205. $groupEndIndex = $groupStartIndex + $groupCount;
  206. for ($i = $groupStartIndex; $i < $groupEndIndex; $i++) {
  207. $item = [
  208. // TODO 新建群默认群主为APP管理员
  209. 'Owner_Account' => config('im.identifier'),
  210. 'Type' => TencentImGroup::IM_GROUP_RAW_TYPE_ChatRoom,
  211. 'Name' => $i,
  212. ];
  213. $this->createGroup($item);
  214. $params[] = $item;
  215. }
  216. unset($item);
  217. return $params;
  218. }
  219. }