SubscribeService.php 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. <?php
  2. namespace App\Services\Goodnight;
  3. use App\Exceptions\AlertException;
  4. use App\Models\Goodnight\InviteLogModel;
  5. use App\Models\Goodnight\SubscribeModel;
  6. use App\Models\Goodnight\TagModel;
  7. use App\Models\Goodnight\UserModel;
  8. use App\Models\Goodnight\VoiceModel;
  9. use App\Services\Service;
  10. use Illuminate\Support\Facades\DB;
  11. use Illuminate\Support\Facades\Redis;
  12. class SubscribeService extends Service
  13. {
  14. public const SUB_TYPE = [
  15. 1 => [
  16. 'description' => '订阅一周',
  17. 'day' => 7,
  18. 'gnight_coin' => 7,
  19. ],
  20. 2 => [
  21. 'description' => '订阅一个月',
  22. 'day' => 30,
  23. 'gnight_coin' => 20,
  24. ],
  25. 3 => [
  26. 'description' => '订阅一年',
  27. 'day' => 365,
  28. 'gnight_coin' => 200,
  29. ],
  30. ];
  31. /**
  32. * 订阅声音
  33. * @param int $uid
  34. * @param int $type
  35. * @return int
  36. * @throws AlertException
  37. */
  38. public function subscribe(int $uid, int $type)
  39. {
  40. $user = UserModel::findOrFail($uid);
  41. if ($user->subscribed_at < time()) {
  42. $time = time();
  43. } else {
  44. $time = $user->subscribed_at;
  45. }
  46. $data = array();
  47. if (0 == $user->subscribed_at && 1 == $type) {
  48. $data['gnight_coin'] = $user->gnight_coin + 3;
  49. $data['subscribed_at'] = $time + self::SUB_TYPE[$type]['day'] * 86400;
  50. $data['subscribe_cnt'] = $user->subscribe_cnt + 1;
  51. } else {
  52. if ($user->gnight_coin < self::SUB_TYPE[$type]['gnight_coin']) {
  53. throw new AlertException("晚安币不足", 202);
  54. }
  55. $data['gnight_coin'] = $user->gnight_coin - self::SUB_TYPE[$type]['gnight_coin'];
  56. $data['subscribed_at'] = $time + self::SUB_TYPE[$type]['day'] * 86400;
  57. $data['subscribe_cnt'] = $user->subscribe_cnt + 1;
  58. }
  59. if (0 == $user->subscribed_at) {
  60. $voice = $this->getRomVoice($uid, [1, 2, 3, 4]);
  61. if ($voice) {
  62. SubscribeModel::create([
  63. 'voice_id' => $voice['id'],
  64. 'uid' => $user->uid,
  65. 'type' => 1,
  66. ]);
  67. }
  68. if (0 != $user->invite_uid) {
  69. UserModel::where('uid', $user->invite_uid)->increment('gnight_coin', 3);
  70. try {
  71. UserModel::where([
  72. ['uid', $uid],
  73. ['gnight_coin', $user->gnight_coin],
  74. ])->update($data);
  75. } catch (\Exception $e) {
  76. UserModel::where('uid', $user->invite_uid)->decrement('gnight_coin', 3);
  77. }
  78. $inlogmodel = new InviteLogModel();
  79. $invite = $inlogmodel->fill([
  80. 'uid' => $user->invite_uid,
  81. 'invite_uid' => $uid,
  82. 'gnight_coin' => 3,
  83. ]);
  84. $invite->save();
  85. return $data['subscribed_at'];
  86. } else {
  87. UserModel::where([
  88. ['uid', $uid],
  89. ['gnight_coin', $user->gnight_coin],
  90. ])->update($data);
  91. return $data['subscribed_at'];
  92. }
  93. } else {
  94. UserModel::where([
  95. ['uid', $uid],
  96. ['gnight_coin', $user->gnight_coin],
  97. ])->update($data);
  98. return $data['subscribed_at'];
  99. }
  100. }
  101. /**
  102. * Rom获取一条语音
  103. * @param int $uid
  104. * @param array $topics
  105. * @return bool
  106. */
  107. public function getRomVoice(int $uid, $topics = array(1, 2, 3, 4))
  108. {
  109. $user = UserModel::findOrFail($uid);
  110. $edvoices = SubscribeModel::where('uid', $user->uid)->get();
  111. $selfvoices = VoiceModel::where('uid', $user->uid)->get();
  112. $voices = VoiceModel::where([
  113. ['check', 1],
  114. ['sex', $user->like_sex],
  115. ])->whereNotIn('id', $edvoices->pluck('voice_id'))
  116. ->whereIn('topic_id', $topics)
  117. ->whereNotIn('id', $selfvoices->pluck('id'))->get();
  118. if (!collect($voices)->isEmpty()) {
  119. $voice = $voices->random();
  120. return $voice->toArray();
  121. }
  122. return false;
  123. }
  124. /**
  125. * 我订阅的晚安列表
  126. * @param int $page
  127. * @param int $limit
  128. * @param int $uid
  129. * @return array
  130. */
  131. public function voices(int $page, int $limit, int $uid)
  132. {
  133. $total = \DB::select(
  134. "select count(*) as aggregate from `kdgx_goodnight_subscribe_voice` as `sub` inner join `kdgx_goodnight_voice` as `voice` on `voice_id` = voice.id where `sub`.`uid` = ? and `voice`.`deleted_at` is null",
  135. [$uid]
  136. );
  137. $voices = \DB::select(
  138. "select `voice`.`id`, `voice`.`uid`, `voice`.`expedit`, `sub`.`created_at`, `cover`, `voice`, `like`, `sub`.`created_at` as `geted_at` from `kdgx_goodnight_subscribe_voice` as `sub` inner join `kdgx_goodnight_voice` as `voice` on `voice_id` = voice.id where `sub`.`uid` = ? and `voice`.`deleted_at` is null order by `sub`.`created_at` desc limit ?, ?",
  139. [$uid, ($page - 1) * $limit, $limit]
  140. );
  141. foreach ($voices as &$voice) {
  142. $tag = TagModel::where([
  143. ['uid', $uid],
  144. ['voice_id', $voice->id],
  145. ])->first();
  146. if (collect($tag)->isEmpty()) {
  147. $voice->tag = "";
  148. } else {
  149. $voice->tag = $tag->tag;
  150. }
  151. }
  152. return array(
  153. 'total' => $total[0]->aggregate,
  154. 'list' => $voices,
  155. );
  156. }
  157. /**
  158. * 推送订阅
  159. */
  160. public function pushload()
  161. {
  162. // 获取有效订阅用户
  163. $today = date('d');
  164. $uids = Redis::hkeys("goodnight:push:{$today}");
  165. $users = UserModel::where('subscribed_at', '>', time())->get();
  166. foreach ($users as $user) {
  167. $voice_id = Redis::hget("goodnight:push:{$today}", $user->uid);
  168. try {
  169. $voice = VoiceModel::findOrFail($voice_id);
  170. } catch (\Exception $e) {
  171. // 筛选声音
  172. $edvoices = SubscribeModel::where('uid', $user->uid)->get();
  173. $selfvoices = VoiceModel::where('uid', $user->uid)->get();
  174. $voices = VoiceModel::where([
  175. ['commit', 1],
  176. ['sex', $user->like_sex],
  177. ])->whereNotIn('id', $edvoices->pluck('voice_id'))
  178. ->whereNotIn('id', $selfvoices->pluck('id'))->get();
  179. if (collect($voices)->isEmpty()) {
  180. continue;
  181. }
  182. $voice = $voices->random();
  183. }
  184. // 送入数据库
  185. SubscribeModel::create([
  186. 'voice_id' => $voice->id,
  187. 'is_push' => 1,
  188. 'uid' => $user->uid,
  189. ]);
  190. VoiceModel::where('id', $voice->id)->increment('view', 1);
  191. // 通知
  192. try {
  193. $ns = new NoticeService();
  194. $ns->subscribe($user->uid, $voice->uid, $voice->id);
  195. } catch (\Exception $e) {
  196. app('sentry')->captureException($e);
  197. }
  198. }
  199. }
  200. /**
  201. * 捞取晚安
  202. * @param int $uid
  203. * @return bool
  204. * @throws AlertException
  205. */
  206. public function fishVoice(int $uid)
  207. {
  208. $cnt = SubscribeModel::where([['uid', $uid], ['type', 2]])->whereBetween(
  209. 'created_at',
  210. [mktime(0, 0, 0), mktime(0, 0, 0) + 86400]
  211. )->count();
  212. if ($cnt >= 10) {
  213. throw new AlertException("漂流瓶获取次数达上限,明天再来吧", 101);
  214. }
  215. $voice = $this->getRomVoice($uid, [1, 2, 3, 4]);
  216. if ($voice) {
  217. DB::beginTransaction();
  218. try {
  219. DB::table('kdgx_goodnight_subscribe_voice')->insert([
  220. 'created_at' => time(),
  221. 'updated_at' => time(),
  222. 'voice_id' => $voice['id'],
  223. 'uid' => $uid,
  224. 'type' => 2,
  225. ]);
  226. DB::commit();
  227. return $voice;
  228. } catch (\Exception $e) {
  229. DB::rollBack();
  230. throw new AlertException('很遗憾未能捞到晚安!');
  231. }
  232. }
  233. throw new AlertException('很遗憾未能捞到晚安');
  234. }
  235. /**
  236. * 获取今日晚安
  237. * @param int $uid
  238. * @return VoiceModel|array
  239. */
  240. public function todayVoice(int $uid)
  241. {
  242. $vsm = new SubscribeModel();
  243. $bet = array(
  244. mktime(21, 30, 0),
  245. mktime(23, 59, 59),
  246. );
  247. $sub = $vsm->where([['uid', $uid], ['is_push', 1]])->whereBetween('created_at', $bet)->first();
  248. if (collect($sub)->isEmpty()) {
  249. return array();
  250. } else {
  251. $vs = new VoiceService();
  252. return $vs->getVoice($uid, $sub->voice_id);
  253. }
  254. }
  255. }