RelationController.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. <?php
  2. /**
  3. * 关系api.
  4. *
  5. * @author ningque
  6. * @date 2020-02-20 02:12:58
  7. */
  8. declare(strict_types=1);
  9. namespace Modules\Api\Controllers;
  10. use App\Constants\CommonConstant;
  11. use App\Model\Mongo\UserRelationModel;
  12. use App\Model\Mongo\VideoLikeModel;
  13. use App\Model\UserModel;
  14. use App\Model\VideoModel;
  15. use App\Repositories\RelationRepository;
  16. use App\Repositories\Service\CommonService;
  17. use App\Repositories\Service\QueueService;
  18. use App\Repositories\UserLevelRelationRepository;
  19. use App\Repositories\UserRepository;
  20. use App\Repositories\Utils\M3u8CacheRepository;
  21. use Carbon\Carbon;
  22. use Hyperf\Validation\Contract\ValidatorFactoryInterface;
  23. use Modules\Api\Services\VideoService;
  24. class RelationController extends BaseController
  25. {
  26. /**
  27. * 关注/取消关注
  28. * @return mixed
  29. */
  30. public function doRelation(ValidatorFactoryInterface $validatorFactory)
  31. {
  32. $userId = $this->getUserId();
  33. $inputData = $this->getJsonData();
  34. $rules = [
  35. 'to_user_id' => 'required|string',
  36. ];
  37. $validator = $validatorFactory->make($inputData, $rules);
  38. if ($validator->fails()) {
  39. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  40. return json_fail($validator->errors()->first());
  41. }
  42. $toUserId = strval(data_get($inputData, 'to_user_id'));
  43. if ($userId == $toUserId) {
  44. return json_fail('自己不能关注自己');
  45. }
  46. $toUserInfo = make(UserRepository::class)->getUserInfoFromCache($toUserId);
  47. if (!$toUserInfo) {
  48. return json_fail('用户关态异常');
  49. }
  50. $favoriteKey = md5('favorite_' . $userId . '_' . $toUserId);
  51. $favoriteData = [
  52. '_id' => $favoriteKey
  53. ];
  54. $favorite = make(UserRelationModel::class)->db()
  55. ->countDocuments($favoriteData);
  56. $focusResult = false;
  57. if ($favorite) {
  58. //若已关注,则取消
  59. make(UserRelationModel::class)->db()->deleteOne($favoriteData);
  60. } else {
  61. $focusResult = true;
  62. //若未关注,则关注
  63. $favoriteData['from_user_id'] = $userId;
  64. $favoriteData['to_user_id'] = $toUserId;
  65. $favoriteData['date'] = Carbon::now()->toDateTimeString();
  66. make(UserRelationModel::class)->db()->insertOne($favoriteData);
  67. }
  68. make(UserRepository::class)->delUserCache($userId);
  69. make(UserRepository::class)->delUserCache($toUserId);
  70. return json_success($focusResult);
  71. }
  72. /**
  73. * 关注列表(含关注和被关注)
  74. * @return mixed
  75. */
  76. public function list(ValidatorFactoryInterface $validatorFactory)
  77. {
  78. $userId = $this->getUserId();
  79. $inputData = $this->getJsonData();
  80. $rules = [
  81. 'type' => 'required|in:favorite,fans',
  82. 'page' => 'nullable|numeric',
  83. 'page_size' => 'nullable|numeric'
  84. ];
  85. $validator = $validatorFactory->make($inputData, $rules);
  86. if ($validator->fails()) {
  87. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  88. return json_fail($validator->errors()->first());
  89. }
  90. $type = data_get($inputData, 'type');
  91. $page = intval(data_get($inputData, 'page', 1));
  92. $pageSize = intval(data_get($inputData, 'page_size', 10));
  93. $skip = ($page -1) * $pageSize;
  94. if ($type == 'favorite') {
  95. $data = [
  96. 'from_user_id' => $userId
  97. ];
  98. } else {
  99. $data = [
  100. 'to_user_id' => $userId
  101. ];
  102. }
  103. $options = [
  104. 'skip' => $skip,
  105. 'limit' => $pageSize,
  106. 'sort' => ['date' => -1],
  107. ];
  108. $tmp = make(UserRelationModel::class)->db()->find($data, $options);
  109. $result['list'] = [];
  110. if ($tmp) {
  111. $ids = [];
  112. $needUserId = $type == 'favorite' ? 'to_user_id' : 'from_user_id';
  113. foreach ($tmp->toArray() as $t) {
  114. $ids[] = $t[$needUserId];
  115. }
  116. $result['list'] = UserModel::query()
  117. ->select(['code','nick','avatar'])
  118. ->whereIn('code', $ids)
  119. ->get();
  120. if (!empty($result['list'])) {
  121. foreach ($result['list'] as $k => $v) {
  122. $result['list'][$k]['avatar'] = M3u8CacheRepository::getImageUrl($result['list'][$k]['avatar']);
  123. }
  124. }
  125. }
  126. return json_success($result);
  127. }
  128. /**
  129. * 我点赞过的视频分页列表.
  130. * @return mixed
  131. */
  132. public function likeVideoList(ValidatorFactoryInterface $validatorFactory)
  133. {
  134. $inputData = $this->getJsonData();
  135. $rules = [
  136. 'is_long' => 'nullable|int', // 目前只有短视频,无视这个参数.
  137. 'page' => 'nullable|numeric',
  138. 'page_size' => 'nullable|numeric'
  139. ];
  140. $validator = $validatorFactory->make($inputData, $rules);
  141. if ($validator->fails()) {
  142. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  143. return json_fail($validator->errors()->first());
  144. }
  145. $page = intval(data_get($inputData, 'page', 1));
  146. $pageSize = intval(data_get($inputData, 'page_size', 10));
  147. $skip = ($page -1) * $pageSize;
  148. $relationRepo = make(RelationRepository::class);
  149. $userCode = $this->getUserId();
  150. $filters = [
  151. 'uid' => $userCode,
  152. ];
  153. $amountVideo = make(VideoLikeModel::class)->db()
  154. ->countDocuments($filters);
  155. $maxPages = ceil($amountVideo / $pageSize);
  156. $options = [
  157. 'skip' => $skip,
  158. 'limit' => $pageSize,
  159. 'sort' => ['date' => -1]
  160. ];
  161. $video_like = make(VideoLikeModel::class)->db()
  162. ->find(['uid' => $userCode], $options)
  163. ->toArray();
  164. $result = [
  165. 'current_page' => $page,
  166. 'data' => [],
  167. 'first_page_url' => '',
  168. 'from' => null,
  169. 'last_page' => $maxPages,
  170. 'last_page_url' => '',
  171. 'next_page_url' => null,
  172. 'path' => '',
  173. 'per_page' => $pageSize,
  174. 'prev_page_url' => '',
  175. 'to' => null,
  176. 'total' => $amountVideo,
  177. ];
  178. $columns = ['id','title', 'cover', 'like', 'uid', 'coins', 'pay_type', 'mu', 'comment', 'watch', 'resolution', 'duration'];
  179. if (!empty($video_like)) {
  180. $arrIds = [];
  181. foreach ($video_like as $v) {
  182. $arrIds[] = $v['vid'];
  183. }
  184. $arrIds = array_slice($arrIds, 0, 100); // 最大100
  185. $id_str = implode(',', $arrIds);
  186. $result2 = VideoModel::query()
  187. ->with(['category:type.id as type_id,type.title','user'])
  188. ->whereIn('id', $arrIds)
  189. ->where(['status' => 1])
  190. ->orderByRaw('field(id,'. $id_str . ')')
  191. ->get($columns);
  192. if (!empty($result2->isNotEmpty())) {
  193. $result['data'] = $result2->toArray();
  194. foreach ($result['data'] as $k => &$v) {
  195. $v['mu'] = ''; // 列表干掉m3u8地址.
  196. // $v['mu'] = M3u8CacheRepository::getVideoInnerUrl($v['mu'], $userCode, $v['id'], 'video');
  197. $v['cover'] = M3u8CacheRepository::getImageUrl($v['cover']);
  198. if (!empty($v['user'])) {
  199. $v['user']['avatar'] = M3u8CacheRepository::getImageUrl($v['user']['avatar']);
  200. // $v['user']['is_focus'] = $relationRepo->userIsFocusOtherUser($userCode, $v['user']['code']);
  201. }
  202. // $v['is_my_like'] = $relationRepo->userIsLikeVideo($userCode, $v['id']);
  203. if (!empty($v['category'])) {
  204. foreach ($v['category'] as $ck => $t) {
  205. unset($v['category'][$ck]['pivot']);
  206. }
  207. }
  208. }
  209. }
  210. }
  211. return json_success($result);
  212. }
  213. /**
  214. * 视频点赞/取消点赞
  215. * @param ValidatorFactoryInterface $validatorFactory
  216. * @return mixed
  217. */
  218. public function likeVideo(ValidatorFactoryInterface $validatorFactory)
  219. {
  220. $user_code = $this->getUserId();
  221. $inputData = $this->getJsonData();
  222. $rules = [
  223. 'video_id' => 'required|int',
  224. ];
  225. $validator = $validatorFactory->make($inputData, $rules);
  226. if ($validator->fails()) {
  227. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  228. return json_fail($validator->errors()->first());
  229. }
  230. $videoId = intval(data_get($inputData, 'video_id', 0));
  231. $key = $user_code .'_'. $videoId;
  232. $_id = substr(md5($key), 8, 16);
  233. $data = [
  234. '_id' => $_id
  235. ];
  236. $count = make(VideoLikeModel::class)->db()->countDocuments($data);
  237. if ($count) {
  238. //若已关注,则取消
  239. make(VideoLikeModel::class)->db()->deleteOne($data);
  240. make(QueueService::class)
  241. ->addVideoLikeJob(
  242. [
  243. 'video_id' => $videoId,
  244. 'amount' => -1
  245. ]
  246. );
  247. $result = 0;
  248. } else {
  249. $videoInfo = VideoModel::query()->find($videoId, ['uid'])->toArray();
  250. //若未关注,则关注
  251. $data['uid'] = $user_code;
  252. $data['vid'] = $videoId;
  253. $data['date'] = Carbon::now()->toDateTimeString();
  254. $data['video_user_uid'] = (string)$videoInfo['uid']; // 记录作者UID
  255. make(VideoLikeModel::class)->db()->insertOne($data);
  256. make(QueueService::class)
  257. ->addVideoLikeJob(
  258. [
  259. 'video_id' => $videoId,
  260. 'amount' => 1
  261. ]
  262. );
  263. $result = 1;
  264. }
  265. make(UserRepository::class)->delUserCache($user_code);
  266. return json_success($result);
  267. }
  268. public function myInvitePages(ValidatorFactoryInterface $validatorFactory)
  269. {
  270. $userCode = $this->getUserId();
  271. $inputData = $this->getJsonData();
  272. $rules = [
  273. 'page' => 'nullable|numeric',
  274. 'page_size' => 'nullable|numeric'
  275. ];
  276. $validator = $validatorFactory->make($inputData, $rules);
  277. if ($validator->fails()) {
  278. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  279. return json_fail($validator->errors()->first());
  280. }
  281. $page = intval(data_get($inputData, 'page', 1));
  282. $pageSize = intval(data_get($inputData, 'page_size', 10));
  283. $lists = make(UserLevelRelationRepository::class)->userInvitePages($userCode, $page, $pageSize);
  284. return json_success($lists);
  285. }
  286. public function followUserPages(ValidatorFactoryInterface $validatorFactory)
  287. {
  288. $userCode = $this->getUserId();
  289. $inputData = $this->getJsonData();
  290. $rules = [
  291. 'user_code' => 'required|max:16',
  292. 'page' => 'nullable|numeric',
  293. 'page_size' => 'nullable|numeric'
  294. ];
  295. $validator = $validatorFactory->make($inputData, $rules);
  296. if ($validator->fails()) {
  297. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  298. return json_fail($validator->errors()->first());
  299. }
  300. $type = 'favorite';
  301. $page = intval(data_get($inputData, 'page', 1));
  302. $pageSize = intval(data_get($inputData, 'page_size', 10));
  303. $page = format_page($page);
  304. if ($pageSize > 50) {
  305. $pageSize = CommonConstant::PAGE_SIZE;
  306. }
  307. $skip = ($page -1) * $pageSize;
  308. $data = [
  309. 'from_user_id' => $inputData['user_code'],
  310. ];
  311. $options = [
  312. 'skip' => $skip,
  313. 'limit' => $pageSize,
  314. 'sort' => ['date' => -1],
  315. ];
  316. $relationRepo = make(UserRelationModel::class);
  317. $amount = $relationRepo->db()->countDocuments($data);
  318. $lists = $relationRepo->db()->find($data, $options);
  319. $arrData = [
  320. 'current_page' => $page,
  321. 'per_page' => $pageSize,
  322. 'total' => $amount,
  323. 'data' => [],
  324. ];
  325. if (!empty($lists)) {
  326. $arrIds = [];
  327. foreach ($lists->toArray() as $v) {
  328. $arrIds[] = $v['to_user_id'];
  329. }
  330. $columns = ['id', 'code', 'nick', 'avatar'];
  331. $users = UserModel::query()
  332. ->whereIn('code', $arrIds)
  333. ->get($columns);
  334. if ($users->count()) {
  335. $users = $users->toArray();
  336. foreach ($users as $v) {
  337. $videoCount = VideoModel::query()->where(['uid' => $v['code'], 'status' => 1])->count();
  338. $arrData['data'][] = [
  339. 'user_code' => $v['code'],
  340. 'nick' => $v['nick'],
  341. 'avatar' => M3u8CacheRepository::getImageUrl($v['avatar']),
  342. 'video_count' => $videoCount,
  343. ];
  344. }
  345. }
  346. }
  347. return json_success($arrData);
  348. }
  349. }