| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960 |
- <?php
- namespace App\Repositories;
- use App\Constants\CommonConstant;
- use App\Constants\VideoConstant;
- use App\Events\Video\VideoReceiveEvent;
- use App\Model\AdModel;
- use App\Model\CommentModel;
- use App\Model\GoodsModel;
- use App\Model\Mongo\VideoHistoryModel;
- use App\Model\Mongo\VideoLikeModel;
- use App\Model\ShopsModel;
- use App\Model\TypeModel;
- use App\Model\TypeVideoModel;
- use App\Model\UserBuyVideoModel;
- use App\Model\UserModel;
- use App\Model\UserTagModel;
- use App\Model\VideoModel;
- use App\Repositories\Utils\M3u8CacheRepository;
- use Carbon\Carbon;
- use KZ2\Repositories\Model\Repository;
- use Modules\Api\Services\VideoService;
- use Psr\SimpleCache\CacheInterface;
- class VideoRepository extends Repository
- {
- public function model()
- {
- return VideoModel::class;
- }
- public function checkExist($hash)
- {
- return VideoModel::query()->where(['file_hash' => $hash])->exists();
- }
- public function createOneToVideo($item)
- {
- if ($item['from_type'] == 1) {
- // 来自系统,则判断是否重复.
- if (self::checkExist($item['file_hash'])) {
- return false;
- }
- }
- $m3u8Url = '';
- $strTags = $item['tags'] ?? '';
- $strScreenshots = $item['screenshots'] ?? '';
- if (!empty($item['multiple_rates']['bit_rates'])) {
- $serverFlag = $item['multiple_rates']['server_flag'] ?? '';
- ksort($item['multiple_rates']['bit_rates'], SORT_NUMERIC); // key 升序
- $bitrate = array_key_first($item['multiple_rates']['bit_rates']);
- $m3u8Uri = $item['multiple_rates']['bit_rates'][$bitrate]['m3u8_uri'] ?? '';
- if (!empty($serverFlag) && !empty($m3u8Uri)) {
- $m3u8Url = $serverFlag . '|' . $m3u8Uri;
- }
- }
- $arrTags = [];
- if (!empty($item['tags'])) {
- if (is_array($item['tags'])) {
- $strTags = implode(',', $item['tags']);
- $arrTags = $item['tags'];
- } else {
- $arrTags = explode(',', $item['tags']);
- }
- }
- if (!empty($item['screenshots'])) {
- if (is_array($item['screenshots'])) {
- $strScreenshots = implode(',', $item['screenshots']);
- }
- }
- // 处理关联标签.
- $tagIdsRaltion = [];
- if (!empty($arrTags)) {
- foreach ($arrTags as $v) {
- $tagObj = TypeModel::query()->where('title', $v)->first();
- if (empty($tagObj)) {
- $tagSaveData = [
- 'title' => $v,
- 'status' => 1,
- 'sort' => 0,
- ];
- $tagObj = TypeModel::query()->create($tagSaveData);
- }
- $tagIdsRaltion[] = $tagObj->id;
- }
- }
- $arrBots = [];
- $userCode = '';
- $bots = UserModel::query()->where('gender', '=', 3)->take(100)->get();
- if ($bots->count()) {
- $arrBots = $bots->pluck('code')->toArray();
- $userKey = array_rand($arrBots);
- $userCode = $arrBots[$userKey];
- }
- $nowDate = Carbon::now()->toDateTimeString();
- $setarr = [
- 'title' => $item['title'],
- 'status' => 1, // 未上架2未上架,1上架,3转码中,4转码失败
- 'mu' => $m3u8Url,
- 'check' => 1, // 默认已审核
- // 'is_free' => 0, // 默认不免费,
- 'type' => 0, // 默认是系统,1= 用户
- 'from' => 0,
- 'online_at' => $nowDate,
- 'duration' => $item['duration'],
- 'bitrate' => $item['bitrate'],
- 'resolution' => $item['resolution'],
- 'tags' => $strTags,
- 'screenshots' => $strScreenshots,
- 'file_hash' => $item['file_hash'],
- 'player_type' => $item['type'],
- 'uid' => $userCode,
- 'watch' => rand(3000, 30000), // 观看次数.
- 'like' => rand(300, 9300), // 点赞数
- ];
- if (!empty($item['cover'])) {
- // mov格式好像无法被ppvod截图,所以要前端先传.
- $setarr['cover'] = $item['cover'];
- }
- $obj = null;
- if (self::checkExist($item['file_hash'])) {
- $obj = VideoModel::query()->where(['file_hash' => $item['file_hash']])->first();
- if ($obj->status > 2) {
- // 只有在转码中的视频才更新信息.
- $arrUpdate = $setarr;
- $arrUpdate['status'] = 2; // 用户上传的默认未上架.
- $arrUpdate['type'] = 1; // 用户
- $arrUpdate['check'] = 0; // 未审核.
- $arrUpdate['online_at'] = null;
- if (!empty($obj->custom_cover)) {
- // 使用用户自定义的图.
- $arrUpdate['cover'] = $obj->custom_cover;
- }
- // $arrUpdate['uid'] = $item['app_item_code'];
- unset($arrUpdate['file_hash'], $arrUpdate['uid'], $arrUpdate['watch'], $arrUpdate['like'], $arrUpdate['title']);
- $updateStatus = $obj->update($arrUpdate);
- }
- } else {
- // 不存在则创建.
- if (!empty($item['app_item_code'])) {
- // 如果有设置绑定用户,则执行.
- $userCode = $item['app_item_code'];
- $userObj = UserModel::query()->where(['code' => $userCode])->first();
- if (empty($userObj)) {
- logger('VideoRepository-createOneToVideo-fail', ['msg' => '用户非系统内用户,无法找到.']);
- return false;
- }
- $setarr['uid'] = $userCode;
- }
- $obj = VideoModel::query()->create($setarr);
- if ($obj) {
- $videoId = $obj->id;
- if (!empty($tagIdsRaltion)) {
- foreach ($tagIdsRaltion as $tagId) {
- $setarr = [
- 'type_id' => $tagId,
- 'video_id' => $videoId,
- 'status' => 1,
- ];
- TypeVideoModel::query()->create($setarr);
- }
- }
- // 开始随机写入评论.
- $commentRepo = make(CommentRepository::class);
- $commentPath = self::getCommentPath();
- if (file_exists($commentPath)) {
- $content = file_get_contents($commentPath);
- $arrComments = explode("\n", $content);
- $users = UserModel::where(['ip' => '113.238.142.208'])->where('gender', '!=', 3)->inRandomOrder()->take(100)->get();
- $arrUsers = $users->pluck('code')->toArray();
- $oldCommentContent = '_1_';
- $commentContent = '';
- $videoCreatedAt = $obj->created_at;
- $maxCommentNumber = rand(2, 24);
- $nowDate = Carbon::now()->toDateTimeString();
- for ($i = 0; $i < $maxCommentNumber; $i++) {
- if (!empty($commentContent)) {
- $oldCommentContent = $commentContent;
- }
- $userKey = array_rand($arrUsers);
- $userCode = $arrUsers[$userKey];
- $commentKey = array_rand($arrComments);
- $commentContent = $arrComments[$commentKey];
- if ($oldCommentContent == $commentContent) {
- // 避免连续重复,再随机一次.
- $commentKey = array_rand($arrComments);
- $commentContent = $arrComments[$commentKey];
- }
- $setarr = [
- 'user_id' => $userCode,
- 'module' => 'video',
- 'svalue' => $obj->id,
- 'subject' => mb_substr($obj->title, 0, 120),
- 'content' => $commentContent,
- 'parent_id' => 0,
- 'total_support' => rand(0, 200),
- 'ip' => '113.238.142.208',
- ];
- $commentObj = $commentRepo->createComment($setarr);
- $commentObj->created_at = Carbon::parse($videoCreatedAt)->addHours($i + 3)->addMinutes(rand(5, 43))->toDateTimeString();
- $commentObj->save();
- }
- }
- }
- }
- return $obj;
- }
- public function createOneToAd($item)
- {
- $m3u8Url = '';
- if (!empty($item['multiple_rates']['bit_rates'])) {
- $serverFlag = $item['multiple_rates']['server_flag'] ?? '';
- ksort($item['multiple_rates']['bit_rates'], SORT_NUMERIC); // key 升序
- $bitrate = array_key_first($item['multiple_rates']['bit_rates']);
- $m3u8Uri = $item['multiple_rates']['bit_rates'][$bitrate]['m3u8_uri'] ?? '';
- if (!empty($serverFlag) && !empty($m3u8Uri)) {
- $m3u8Url = $serverFlag . '|' . $m3u8Uri;
- }
- }
- $adId = $item['app_item_code'];
- $obj = AdModel::query()->find($adId);
- if (!empty($obj)) {
- $obj->play = $m3u8Url;
- if ($obj->status == 3) {
- // 只有特定状态才改变
- $obj->status = 2; // 转码中 -> 未上架.
- }
- $saveStatus = $obj->save();
- }
- return $obj;
- }
- public function createOneToShop($item)
- {
- $m3u8Url = '';
- if (!empty($item['multiple_rates']['bit_rates'])) {
- $serverFlag = $item['multiple_rates']['server_flag'] ?? '';
- ksort($item['multiple_rates']['bit_rates'], SORT_NUMERIC); // key 升序
- $bitrate = array_key_first($item['multiple_rates']['bit_rates']);
- $m3u8Uri = $item['multiple_rates']['bit_rates'][$bitrate]['m3u8_uri'] ?? '';
- if (!empty($serverFlag) && !empty($m3u8Uri)) {
- $m3u8Url = $serverFlag . '|' . $m3u8Uri;
- }
- }
- $relationUid = $item['app_item_code'];
- $obj = ShopsModel::query()->where(['uid' => $relationUid])->first();
- if (!empty($obj)) {
- $obj->video_address = $m3u8Url;
- $saveStatus = $obj->save();
- // 删除缓存
- $cacheKey = 'shop:raw:'. $relationUid . ':empty';
- $cacheRepo = make(CacheInterface::class);
- $cacheRepo->delete($cacheKey);
- }
- return $obj;
- }
- public function createOneToGoods($item)
- {
- $m3u8Url = '';
- if (!empty($item['multiple_rates']['bit_rates'])) {
- $serverFlag = $item['multiple_rates']['server_flag'] ?? '';
- ksort($item['multiple_rates']['bit_rates'], SORT_NUMERIC); // key 升序
- $bitrate = array_key_first($item['multiple_rates']['bit_rates']);
- $m3u8Uri = $item['multiple_rates']['bit_rates'][$bitrate]['m3u8_uri'] ?? '';
- if (!empty($serverFlag) && !empty($m3u8Uri)) {
- $m3u8Url = $serverFlag . '|' . $m3u8Uri;
- }
- }
- $relationUid = $item['app_item_code'];
- $obj = GoodsModel::query()->where(['uid' => $relationUid])->first();
- if (!empty($obj)) {
- $obj->video_address = $m3u8Url;
- $saveStatus = $obj->save();
- // 删除缓存
- $cacheKey = 'goods:raw:'. $relationUid . ':empty';
- $cacheRepo = make(CacheInterface::class);
- $cacheRepo->delete($cacheKey);
- }
- return $obj;
- }
- public function createOneFromMediaCenter($item)
- {
- $resultObj = null;
- if ($item['from_type'] == 1) {
- $resultObj = $this->createOneToVideo($item);
- } elseif ($item['from_type'] == 2) {
- $resultObj = $this->createOneToVideo($item);
- } elseif ($item['from_type'] == 3) {
- if ($item['app_module_name'] == 'ad') {
- $resultObj = $this->createOneToAd($item);
- } elseif ($item['app_module_name'] == 'shop') {
- $resultObj = $this->createOneToShop($item);
- } elseif ($item['app_module_name'] == 'goods') {
- $resultObj = $this->createOneToGoods($item);
- }
- }
- if (!empty($resultObj)) {
- $eventParams = [
- 'from_type' => $item['from_type'],
- 'app_alias_name' => $item['app_alias_name'],
- 'app_module_name' => $item['app_module_name'],
- 'app_item_code' => $item['app_item_code'],
- 'video_info' => $resultObj->toArray(),
- ];
- dispatch_event(new VideoReceiveEvent($eventParams));
- }
- }
- /**
- * 某个标签下的视频分页列表.
- * @param $tagId
- * @param string $userCode
- * @param int $page
- * @param int $pageSize
- * @param array $orderBy
- * @return array
- */
- public function listByTag($tagId, $userCode, $page = 1, $pageSize = 10, $orderBy = [])
- {
- $columns = ['id','title', 'cover', 'like', 'uid', 'coins', 'pay_type', 'comment', 'mu', 'watch', 'resolution', 'duration'];
- $page = $page ? intval($page) : 1;
- $pageSize = intval($pageSize);
- if (empty($pageSize)) {
- $pageSize = 12;
- }
- $model = VideoModel::query()->whereHas('tags', function ($q) use ($tagId) {
- $q->where(['type_id' => $tagId]);
- })->where(['status' => 1])
- ->with(['category:type.id as type_id,type.title','user']);
- if (!empty($orderBy)) {
- foreach ($orderBy as $oby) {
- $model = $model->orderBy($oby[0], $oby[1]);
- }
- } else {
- $model = $model->orderBy('id', 'desc');
- }
- $arrData = $model->paginate($pageSize, $columns, 'page', $page)->toArray();
- if (!empty($arrData['data'])) {
- // $relationRepo = make(RelationRepository::class);
- foreach ($arrData['data'] as &$v) {
- $v['mu'] = ''; // 列表干掉m3u8地址.
- // $v['mu'] = M3u8CacheRepository::getVideoInnerUrl($v['mu'], $userCode, $v['id'], 'video');
- $v['cover'] = M3u8CacheRepository::getImageUrl($v['cover']);
- if (!empty($v['user'])) {
- $v['user']['avatar'] = M3u8CacheRepository::getImageUrl($v['user']['avatar']);
- // $v['user']['is_focus'] = $relationRepo->userIsFocusOtherUser($userCode, $v['user']['code']);
- }
- // $v['is_my_like'] = $relationRepo->userIsLikeVideo($userCode, $v['id']);
- if (!empty($v['category'])) {
- foreach ($v['category'] as $ck => $t) {
- unset($v['category'][$ck]['pivot']);
- }
- }
- }
- }
- return $arrData;
- }
- /**
- * 某用户关注的标签下的视频分页列表.
- * @param string $userCode
- * @param int $page
- * @param int $pageSize
- * @return array
- */
- public function listByUserFollowTag($userCode, $page = 1, $pageSize = 10)
- {
- $page = $page ? intval($page) : 1;
- $pageSize = intval($pageSize);
- $page = format_page($page);
- $tagIds = [];
- $userTags = UserTagModel::where(['user_uid' => $userCode])->get();
- if ($userTags->count()) {
- $tagIds = $userTags->pluck('tag_id')->toArray();
- }
- $columns = ['id','title', 'cover', 'like', 'uid', 'coins', 'pay_type', 'comment', 'mu', 'watch', 'resolution'];
- $arrData = VideoModel::query()->with(['category:type.id as type_id,type.title', 'user'])->where(['status' => 1])
- ->whereHas('tags', function ($q) use ($tagIds) {
- if (!empty($tagIds)) {
- $q->whereIn('type_id', $tagIds);
- } else {
- $q->where('type_id', '-999');
- }
- })->orderByDesc('id')->paginate($pageSize, $columns, 'page', $page)->toArray();
- if (!empty($arrData['data'])) {
- // $relationRepo = make(RelationRepository::class);
- foreach ($arrData['data'] as &$item) {
- $item['mu'] = ''; // 列表干掉m3u8地址.
- // $item['mu'] = M3u8CacheRepository::getVideoInnerUrl($item['mu'], $userCode, $item['id'], 'video');
- $item['cover'] = M3u8CacheRepository::getImageUrl($item['cover']);
- if (!empty($item['user'])) {
- $item['user']['avatar'] = !empty($item['user']['avatar']) ? M3u8CacheRepository::getImageUrl($item['user']['avatar']) : '';
- // $item['user']['is_focus'] = $relationRepo->userIsFocusOtherUser($userCode, $item['user']['code']);
- }
- // $item['is_my_like'] = $relationRepo->userIsLikeVideo($userCode, $item['id']);
- if (!empty($item['category'])) {
- foreach ($item['category'] as $ck => $t) {
- unset($item['category'][$ck]['pivot']);
- }
- }
- }
- }
- return $arrData;
- }
- /**
- * 造并返回一个桶视频集合.
- * @param string $step
- * @param mixed $type 类型,no_vip=非vip桶
- * @return mixed
- */
- public function makeOneGroup(string $step, $type = null)
- {
- $configRepo = make(ConfigRepoistory::class);
- $stepDelimiter = intval($configRepo->get('ad_delimiter_num', 'sys', 10)); // 间隔视频几个出现视频.
- $cacheTtl = 48 * 60 * 60;
- $step = strval($step);
- $cache = make(CacheInterface::class);
- $cacheKey = VideoConstant::HOME_GROUP_CACHE_KEY_PREFIX . $step;
- $limitNum = VideoConstant::HOME_GROUP_CHUNK_SIZE;
- $plusWhere = [
- 'status' => 1,
- ];
- if (!is_null($type)) {
- if ($type == 'no_vip') {
- $plusWhere['recommend_level'] = 1;
- $cacheKey = VideoConstant::HOME_NOVIP_GROUP_CACHE_KEY_PREFIX . $step;
- $limitNum = VideoConstant::HOME_NOVIP_GROUP_CHUNK_SIZE;
- }
- }
- // $relationRepo = make(RelationRepository::class);
- // $arrAds = [];
- $arrAds = make(VideoService::class)->getAdList('video_home');
- $result = $cache->rememberForever($cacheKey, function () use ($type, $step, $arrAds, $stepDelimiter, $limitNum) {
- $arrData = [];
- $startNum = $step * $limitNum;
- $arrItems = array_slice($this->getShuffleVideo($type), $startNum, $limitNum);
- if (!empty($arrItems)) {
- $adStep = 1;
- foreach ($arrItems as $k => $v) {
- $arrData[] = [
- 'type' => 'v',
- 'video' => $v,
- ];
- if ($k != 0 && $adStep % $stepDelimiter == 0 && !empty($arrAds)) {
- $arrData[] = [
- 'type' => 'a',
- 'video' => self::getRandAdFromAds($arrAds),
- ];
- }
- $adStep++;
- }
- unset($arrItems);
- }
- return $arrData;
- });
- return $result;
- }
- /**
- * 初始化首页推荐视频多个桶.
- * @return bool
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function initHomeVideoGroups()
- {
- // $this->videoPond();
- // $this->videoPond('no_vip');
- $cacheRepo = make(CacheInterface::class);
- $videoRepo = make(VideoRepository::class);
- $maxPondNum = $videoRepo->getMaxPondNum(null, true);
- $cacheTmpKey = 'video_shuffle:common';
- $cacheRepo->delete($cacheTmpKey);
- for ($i = 0; $i <= $maxPondNum; $i++) {
- $cacheKey = VideoConstant::HOME_GROUP_CACHE_KEY_PREFIX . strval($i);
- if ($cacheRepo->has($cacheKey)) {
- $cacheRepo->delete($cacheKey);
- }
- $this->makeOneGroup($i, null);
- }
- $cacheTmpKey = 'video_shuffle:no_vip';
- $cacheRepo->delete($cacheTmpKey);
- $maxPondNum = $videoRepo->getMaxPondNum('no_vip', true);
- for ($i = 0; $i <= $maxPondNum; $i++) {
- $cacheKey = VideoConstant::HOME_NOVIP_GROUP_CACHE_KEY_PREFIX . strval($i);
- if ($cacheRepo->has($cacheKey)) {
- $cacheRepo->delete($cacheKey);
- }
- $this->makeOneGroup($i, 'no_vip');
- }
- return true;
- }
- /**
- * 清理一个或者所有首页推荐视频桶缓存.
- * @param null $step
- * @return bool
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function clearHomeVideoGroup($step = null)
- {
- $cache = make(CacheInterface::class);
- if (!is_null($step)) {
- $cacheKey = VideoConstant::HOME_GROUP_CACHE_KEY_PREFIX . strval($step);
- $cache->delete($cacheKey);
- } else {
- for ($i = 0; $i <= VideoConstant::HOME_GROUP_NUM; $i++) {
- $cacheKey = VideoConstant::HOME_GROUP_CACHE_KEY_PREFIX . strval($i);
- $cache->delete($cacheKey);
- }
- }
- return true;
- }
- /**
- * 从广告集合随机取一个.
- * @param $arrAds
- * @return array
- */
- public function getRandAdFromAds($arrAds)
- {
- // 间隔N个视频插播一个广告
- $randKey = array_rand($arrAds);
- $adOne = $arrAds[$randKey];
- $adItem = [
- 'id' => $adOne['id'],
- 'position' => $adOne['position'],
- 'title' => $adOne['title'],
- 'cover' => !empty($adOne['cover']) ? $adOne['cover'] : '',
- 'link' => $adOne['link'] ?? '',
- 'scheme' => $adOne['scheme'] ?? '',
- 'type' => $adOne['type'] ?? '',
- 'play' => !empty($adOne['play']) ? $adOne['play'] : '', // 不缓存
- 'resolution' => $adOne['resolution'] ?? '',
- ];
- return $adItem;
- }
- /**
- * 获取评论路径.
- * @return string
- */
- private function getCommentPath()
- {
- return base_path(). '/storage/txt/comment.txt';
- }
- /**
- * 硬删视频,并处理关联关系.
- * @param array $ids
- * @return bool
- */
- public function hardDelete(array $ids)
- {
- if (empty($ids)) {
- return false;
- }
- // 删除
- VideoModel::query()->whereIn('id', $ids)->forceDelete();
- make(VideoHistoryModel::class)->db()->deleteMany(['vid' => ['$in' => $ids]])->getDeletedCount();
- make(VideoLikeModel::class)->db()->deleteMany(['vid' => ['$in' => $ids]])->getDeletedCount();
- CommentModel::query()->where(['module' => 'video'])->whereIn('svalue', $ids)->delete();
- TypeVideoModel::query()->whereIn('video_id', $ids)->delete();
- UserBuyVideoModel::query()->whereIn('video_id', $ids)->delete();
- return true;
- }
- /**
- * 固定视频桶.
- * @param null $type
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function videoPond($type = null)
- {
- $perNum = VideoConstant::HOME_GROUP_CHUNK_SIZE;
- $plusWhere = [
- 'status' => 1,
- ];
- if (!is_null($type)) {
- if ($type == 'no_vip') {
- $plusWhere['recommend_level'] = 1;
- $perNum = VideoConstant::HOME_NOVIP_GROUP_CHUNK_SIZE;
- }
- }
- $pondNum = $this->getMaxPondNum($type, true);
- if ($pondNum <= 0) {
- // 容错,如果系统里没有任何首页非会员视频
- unset($plusWhere['recommend_level']);
- $pondNum = $this->getMaxPondNum(null, true);
- }
- $configRepo = make(ConfigRepoistory::class);
- $stepDelimiter = intval($configRepo->get('ad_delimiter_num', 'sys', 10)); // 间隔视频几个出现视频.
- $arrAds = make(VideoService::class)->getAdList('video_home');
- $columns = ['id','title', 'cover', 'like', 'uid', 'coins', 'pay_type', 'mu', 'comment', 'watch', 'resolution', 'duration'];
- // $count = VideoModel::query()->where($plusWhere)->count('id');
- $adStep = 1;
- $i = 0;
- $arrData = [];
- VideoModel::query()->where($plusWhere)->select($columns)->with(['category:type.id as type_id,type.title','user'])
- ->orderByDesc('id')->chunk($pondNum, function ($items) use (&$arrData, $perNum, $stepDelimiter, $arrAds, &$adStep, &$i) {
- if ($i >= $perNum) {
- // 防止超出每桶视频个数.
- return false;
- }
- if ($items->count() > 0) {
- $arrItems = $items->toArray();
- shuffle($arrItems); // 打乱数组
- $k = 0;
- foreach ($arrItems as $v) {
- $v['mu'] = ''; // 列表干掉m3u8地址.
- // 因为缓存,m3u8链接不能走缓存,保留原始.
- // $v['mu'] = M3u8CacheRepository::getVideoUrl($v['mu']);
- $v['cover'] = M3u8CacheRepository::getImageUrl($v['cover']);
- if (!empty($v['user'])) {
- $v['user']['avatar'] = !empty($v['user']['avatar']) ? M3u8CacheRepository::getImageUrl($v['user']['avatar']) : '';
- }
- if (!empty($v['category'])) {
- foreach ($v['category'] as $ck => $t) {
- unset($v['category'][$ck]['pivot']);
- }
- }
- $arrData[$k][] = [
- 'type' => 'v',
- 'video' => $v,
- ];
- if ($i != 0 && $i % $stepDelimiter == 0 && !empty($arrAds)) {
- $arrData[$k][] = [
- 'type' => 'a',
- 'video' => self::getRandAdFromAds($arrAds),
- ];
- }
- $k++;
- }
- unset($arrItems);
- }
- $i++; // 甩桶次数
- });
- if (!empty($arrData)) {
- $cacheRepo = make(CacheInterface::class);
- foreach ($arrData as $k => $v) {
- $cacheKey = VideoConstant::HOME_GROUP_CACHE_KEY_PREFIX . $k;
- if (!is_null($type)) {
- if ($type == 'no_vip') {
- $cacheKey = VideoConstant::HOME_NOVIP_GROUP_CACHE_KEY_PREFIX . $k;
- }
- }
- if (count($v) < $perNum) {
- $v = $arrData[$k - 1];
- }
- $cacheRepo->forever($cacheKey, $v);
- }
- }
- }
- public function countHomeVideo($type = null, $isForce = false)
- {
- $cacheRepo = make(CacheInterface::class);
- $cacheKey = 'video_home_count';
- $cacheTime = 1 * 60 * 60;
- $data = $cacheRepo->get($cacheKey, -1);
- if ($data < 0 || $isForce == true) {
- $plusWhere = [
- 'status' => 1,
- ];
- if (!is_null($type)) {
- if ($type == 'no_vip') {
- $plusWhere['recommend_level'] = 1;
- }
- }
- $count = VideoModel::query()->where($plusWhere)->count('id');
- $data = $count;
- $cacheRepo->set($cacheKey, $data, $cacheTime);
- }
- return $data;
- }
- /**
- * 获取有效.
- * @param null $type
- * @param false $isForce
- * @return int
- */
- public function getMaxPondNum($type = null, $isForce = false)
- {
- $pondNum = VideoConstant::HOME_GROUP_NUM;
- $perNum = VideoConstant::HOME_GROUP_CHUNK_SIZE;
- if (!is_null($type)) {
- if ($type == 'no_vip') {
- $pondNum = VideoConstant::HOME_NOVIP_GROUP_NUM;
- $perNum = VideoConstant::HOME_NOVIP_GROUP_CHUNK_SIZE;
- }
- }
- $count = $this->countHomeVideo($type, $isForce);
- $maxNum = $pondNum * $perNum;
- if ($maxNum > $count) {
- $pondNum = intval($count / $perNum);
- }
- return $pondNum;
- }
- /**
- * 所有打乱视频.
- * @param null $type
- * @param false $isForce
- * @return array
- */
- protected function getShuffleVideo($type = null, $isForce = false)
- {
- $typeFlag = 'common';
- $plusWhere = [
- 'status' => 1,
- ];
- if (!is_null($type)) {
- if ($type == 'no_vip') {
- $plusWhere['recommend_level'] = 1;
- $typeFlag = 'no_vip';
- }
- }
- $cacheRepo = make(CacheInterface::class);
- $cacheKey = 'video_shuffle:'. $typeFlag;
- $arrData = $cacheRepo->get($cacheKey, []);
- if (empty($arrData) || $isForce == true) {
- $arrData = [];
- $i = 0;
- $columns = ['id', 'title', 'cover', 'like', 'uid', 'coins', 'pay_type', 'mu', 'comment', 'watch', 'resolution', 'duration'];
- VideoModel::query()->where($plusWhere)->select($columns)->with(['category:type.id as type_id,type.title', 'user'])
- ->orderByDesc('id')->chunk(100, function ($items) use (&$arrData, &$i) {
- $i++;
- if ($i > 3000) {
- // 退出chunk
- return false;
- }
- if ($items->count()) {
- $items = $items->toArray();
- foreach ($items as $v) {
- // 因为缓存,m3u8链接不能走缓存,保留原始.
- // $v['mu'] = M3u8CacheRepository::getVideoUrl($v['mu']);
- if (!empty($v['category'])) {
- foreach ($v['category'] as $ck => $t) {
- unset($v['category'][$ck]['pivot']);
- }
- }
- $arrData[] = $v;
- }
- }
- });
- shuffle($arrData);//打乱保存
- $cacheRepo->forever($cacheKey, $arrData);
- }
- return $arrData;
- }
- /**
- * 最新分页视频.
- * @param int $page
- * @param int $pageSize
- * @return array
- */
- public function lastestPagesWihoutCache($page = 1, $pageSize = 30)
- {
- $items = [];
- $columns = ['id', 'title', 'cover', 'like', 'uid', 'coins', 'pay_type', 'mu', 'comment', 'watch', 'resolution', 'duration'];
- $lists = VideoModel::query()->where(['status' => 1])->with(['category:type.id as type_id,type.title', 'user'])->orderByDesc('created_at')->paginate($pageSize, $columns, 'page', $page);
- $lists = $lists->toArray();
- if (!empty($lists['data'])) {
- foreach ($lists['data'] as &$v) {
- // 因为缓存,m3u8链接不能走缓存,保留原始.
- // $v['mu'] = M3u8CacheRepository::getVideoUrl($v['mu']);
- // $v['cover'] = M3u8CacheRepository::getImageUrl($v['cover']);
- // if (!empty($v['user'])) {
- // $v['user']['avatar'] = !empty($v['user']['avatar']) ? M3u8CacheRepository::getImageUrl($v['user']['avatar']) : '';
- // }
- if (!empty($v['category'])) {
- foreach ($v['category'] as $ck => $t) {
- unset($v['category'][$ck]['pivot']);
- }
- }
- unset($v['status'], $v['check']);
- }
- }
- return $lists;
- }
- /**
- * 最新分页视频带缓存.
- * @param int $page
- * @param int $pageSize
- * @param false $isForce
- * @return mixed
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function lastestPages($page = 1, $pageSize = 10, $isForce = false)
- {
- if ($pageSize > 100) {
- $pageSize = CommonConstant::PAGE_SIZE;
- }
- $page = format_page($page);
- $pageSize = intval($pageSize);
- if ($page < 1) {
- $page = 1;
- }
- if ($page > 99999) {
- $page = 1;
- }
- if ($page > 100) {
- // 限制,防止拉完所有视频
- $page = 1;
- }
- $cacheRepo = make(CacheInterface::class);
- $cacheTime = 6 * 60 * 60;
- $cacheKey = 'video:pages:'. strval($page) . '_' . strval($pageSize);
- $data = $cacheRepo->get($cacheKey, []);
- if (empty($data) || $isForce == true) {
- $data = $this->lastestPagesWihoutCache($page, $pageSize);
- if (!empty($data['data'])) {
- $cacheRepo->set($cacheKey, $data, $cacheTime);
- }
- }
- return $data;
- }
- /**
- * 清理所有分页缓存.
- * @param int $pageSize
- * @return bool
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function clearAllLastestPagesCache($pageSize = 10)
- {
- $cacheRepo = make(CacheInterface::class);
- $page = 1;
- $pageSize = VideoConstant::LASTEST_PAGE_SIZE;; // 写死.
- $lists = $this->lastestPagesWihoutCache($page, $pageSize);
- $lastPage = $lists['last_page'] ?? 1;
- $arrKeys = [];
- for ($i = 1; $i <= $lastPage; $i++) {
- $cacheKey = 'video:pages:'. strval($i) . '_' . strval($pageSize);
- $arrKeys[] = $cacheKey;
- }
- // 批量删除缓存.
- $cacheRepo->deleteMultiple($arrKeys);
- return true;
- }
- /**
- * 分类别名下的视频分页.
- * @param string $aliasName
- * @param int $page
- * @param int $pageSize
- * @param false $isForce
- * @return mixed
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function pagesByCategoryAlias($aliasName, $page = 1, $pageSize = 10, $isForce = false)
- {
- if ($pageSize > 100) {
- $pageSize = CommonConstant::PAGE_SIZE;
- }
- $page = format_page($page);
- $pageSize = intval($pageSize);
- if ($page < 1) {
- $page = 1;
- }
- if ($page > 99999) {
- $page = 1;
- }
- if ($page > 100) {
- // 限制,防止拉完所有视频
- $page = 1;
- }
- if ($pageSize <= 0) {
- $pageSize = CommonConstant::PAGE_SIZE;
- }
- $cacheRepo = make(CacheInterface::class);
- $cacheTime = 30 * 60;
- $cacheKey = 'video:pages_cate:'. $aliasName . '_'. strval($page) . '_' . strval($pageSize);
- $data = $cacheRepo->get($cacheKey, []);
- if (empty($data) || $isForce == true) {
- $data = $this->pagesByCategoryAliasWihoutCache($aliasName, $page, $pageSize);
- if (!empty($data['data'])) {
- $cacheRepo->set($cacheKey, $data, $cacheTime);
- }
- }
- return $data;
- }
- /**
- * 分类别名下的视频分页,不带缓存.
- * @param string $aliasName
- * @param int $page
- * @param int $pageSize
- * @return array
- */
- public function pagesByCategoryAliasWihoutCache($aliasName, $page = 1, $pageSize = 30)
- {
- $items = [];
- $columns = ['id', 'title', 'cover', 'like', 'uid', 'coins', 'pay_type', 'mu', 'comment', 'watch', 'resolution', 'duration'];
- $lists = VideoModel::query()->where(['status' => 1])->with(['perfect', 'user', 'category:type.id as type_id,type.title'])->whereHas('perfect', function ($q) use ($aliasName) {
- $q->where(['category_alias_name' => $aliasName]);
- })->orderByDesc('online_at')->paginate($pageSize, $columns, 'page', $page);
- $lists = $lists->toArray();
- if (!empty($lists['data'])) {
- foreach ($lists['data'] as &$v) {
- // 因为缓存,m3u8链接不能走缓存,保留原始.
- // $v['mu'] = M3u8CacheRepository::getVideoUrl($v['mu']);
- // $v['cover'] = M3u8CacheRepository::getImageUrl($v['cover']);
- // if (!empty($v['user'])) {
- // $v['user']['avatar'] = !empty($v['user']['avatar']) ? M3u8CacheRepository::getImageUrl($v['user']['avatar']) : '';
- // }
- if (!empty($v['category'])) {
- foreach ($v['category'] as $ck => $t) {
- unset($v['category'][$ck]['pivot']);
- }
- }
- unset($v['status'], $v['check']);
- }
- }
- return $lists;
- }
- }
|