KeepContinueRead.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: z-yang
  5. * Date: 2019/8/20
  6. * Time: 14:00
  7. */
  8. namespace App\Console\Commands\SmartPush;
  9. use Illuminate\Console\Command;
  10. use DB;
  11. use Redis;
  12. use App\Modules\Book\Services\BookConfigService;
  13. use GuzzleHttp\Client;
  14. use App\Http\Controllers\WechatController;
  15. use GuzzleHttp\Psr7\Request as GuzzleRequest;
  16. use Hashids;
  17. use GuzzleHttp\Pool;
  18. class KeepContinueRead extends Command
  19. {
  20. /**
  21. * The name and signature of the console command.
  22. *
  23. * @var string
  24. */
  25. protected $signature = 'SmartPush:KeepContinueRead';
  26. /**
  27. * The console command description.
  28. *
  29. * @var string
  30. */
  31. protected $description = '持续阅读推送';
  32. /**
  33. * Create a new command instance.
  34. *
  35. * @return void
  36. */
  37. public function __construct()
  38. {
  39. parent::__construct();
  40. }
  41. /**
  42. * Execute the console command.
  43. *
  44. * @return mixed
  45. */
  46. public function handle()
  47. {
  48. $this->send();
  49. }
  50. private function generateRequest()
  51. {
  52. $switch_array = [];
  53. $now_hour = date('G');
  54. $temp = 0;
  55. $continueReadUrlFormat = 'https://site%s.%s.com%s';
  56. while (true){
  57. $user = DB::connection('api_mysql')->table('temp_force_subscribe_users')
  58. ->select('id','uid','distribution_channel_id','openid','appid')
  59. ->where('id','>',$temp)
  60. ->orderBy('id')
  61. ->limit(1000)
  62. ->get();
  63. if(!$user) break;
  64. foreach ($user as $item){
  65. /*if(!in_array($item->distribution_channel_id,[5,8,123,146,155,160,211,255,256,691,695,722,4025,4053,4174,4236,4237,4241,4326,4334,4364,4426,4427,4487,4488,4556,4593,4742,4889,4891,5204,5611,6122,6123,6124,6460,6907,6929,6987])){
  66. continue;
  67. }*/
  68. \Log::info( '---------------------------start--start-------------------------------------------' );
  69. //\Log::info('$item->distribution_channel_id is :'.$item->distribution_channel_id );
  70. \Log::info( '$item->id is :'.$item->id );
  71. if(!isset($switch_array[$item->distribution_channel_id])){
  72. $switch = DB::connection('api_mysql')->table('custom_msg_switchs_msgs')
  73. ->where('distribution_channel_id',$item->distribution_channel_id)
  74. ->where('custom_category','continue_read')
  75. ->select('status')
  76. ->first();
  77. if($switch){
  78. $switch_array[$item->distribution_channel_id] = $switch->status;
  79. }else{
  80. $switch_array[$item->distribution_channel_id] = 1;
  81. }
  82. }
  83. $switch_status = $switch_array[$item->distribution_channel_id];
  84. if($switch_status == 2) continue;
  85. //\Log::info( '$item->distribution_channel_id in is :'.$item->distribution_channel_id );
  86. $read_info = $this->getFirstReadRecord($item->uid);
  87. //\Log::info( $read_info );
  88. \Log::info( 'uid is :'.$item->uid );
  89. if(!$read_info) continue;
  90. //获取本次发送的时间间隔
  91. $this_push_hour = Redis::hget('book_read:'.$item->uid,'next_push_hour');
  92. //上次发送时间
  93. $prev_send_info = DB::connection('api_mysql')->table('custom_push_keep_continue')->where('uid',$item->uid)->select('send_time')->orderBy('id','desc')->first();
  94. $diff = $this_push_hour?$this_push_hour:8;
  95. if($diff == 8){
  96. if((time()-$read_info['time']) > 3600*8){
  97. $send_hour = $now_hour;
  98. }else{
  99. $send_hour = -1;
  100. }
  101. }else{
  102. if($prev_send_info){
  103. //$send_hour = date('G',strtotime($prev_send_info->send_time)+$diff*3600);
  104. if((time()-strtotime($prev_send_info->send_time)) >$diff*3600){
  105. $send_hour = $now_hour;
  106. }else{
  107. $send_hour = -1;
  108. }
  109. }else{
  110. $send_hour = $now_hour;
  111. }
  112. }
  113. if($send_hour != $now_hour ) continue;
  114. $openid = $item->openid;
  115. $appid = $item->appid;
  116. $content_format = "您看的小说有更新\r\n\r\n<a href='%s'>《%s》剧情已更新,点击继续阅读</a> \r\n\r\n记得点击菜单栏签到领书币哦";
  117. $content = sprintf($content_format,
  118. sprintf($continueReadUrlFormat,
  119. encodeDistributionChannelId($item->distribution_channel_id),
  120. env('CUSTOM_HOST'),
  121. $read_info['url']
  122. ),
  123. $read_info['book_name']
  124. );
  125. $accecc_token = $this->getAccessToken($appid);
  126. if(!$accecc_token)continue;
  127. $url = 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token='.$accecc_token;
  128. $request = new GuzzleRequest('post',$url,[],\GuzzleHttp\json_encode([
  129. 'touser'=>$openid,
  130. 'msgtype'=>'text',
  131. 'text'=>['content'=>$content]
  132. ],JSON_UNESCAPED_UNICODE));
  133. DB::connection('api_mysql')->table('custom_push_keep_continue')->insert([
  134. 'uid'=>$item->uid,
  135. 'time_diff'=>$diff,
  136. 'send_time'=>date('Y-m-d H:i:s'),
  137. 'day'=>date('Y-m-d'),
  138. 'created_at'=>date('Y-m-d H:i:s'),
  139. 'updated_at'=>date('Y-m-d H:i:s')
  140. ]);
  141. if($diff == 8){
  142. $next = 5;
  143. }else{
  144. $next = 12;
  145. }
  146. Redis::hset('book_read:'.$item->uid,'next_push_hour',$next);
  147. \Log::info( '----------------------------end-end-end-------------------------------------------' );
  148. yield $request;
  149. }
  150. $temp = $item->id;
  151. }
  152. }
  153. private function getFirstReadRecord($uid){
  154. //Redis::hget('book_base:' . $uid, 'last_read', "{$bid}_{$cid}_{$book_name}_{$chapter_name}_" . time());
  155. $record = Redis::hget('book_read:' . $uid, 'last_read');
  156. if($record){
  157. $record_arr = explode('_',$record);
  158. $bid = $record_arr[0];
  159. $book_name = $this->bid2BookName($bid);
  160. $bid = Hashids::encode($bid);
  161. $cid = $record_arr[1];
  162. $time = $record_arr[2];
  163. $res = [
  164. 'url' => '/reader?bid='.$bid.'&cid='.$cid.'&fromtype=continue_read',
  165. 'book_name'=>$book_name,
  166. 'bid'=>$bid,
  167. 'time'=>$time
  168. ];
  169. return $res;
  170. }
  171. return [];
  172. }
  173. private function bid2BookName($bid){
  174. $book_name = null;
  175. if(is_null($book_name)){
  176. $book_key = 'wap:string:book:'.$bid;
  177. $book_name = Redis::get($book_key);
  178. Redis::EXPIRE($book_key,3600);
  179. if(!$book_name){
  180. $book_name = '';
  181. $book_info = BookConfigService::getBookById($bid);
  182. if($book_info && isset($book_info->book_name)){
  183. $book_name = $book_info->book_name;
  184. }
  185. }
  186. }
  187. return $book_name;
  188. }
  189. private function getAccessToken($appid){
  190. $WechatController = new WechatController($appid);
  191. $accessToken = $WechatController->app->access_token; // EasyWeChat\Core\AccessToken 实例
  192. $token = $accessToken->getToken(); // token 字符串
  193. return $token;
  194. }
  195. private function send(){
  196. $client = new Client();
  197. $requests = $this->generateRequest();
  198. $pool = new Pool($client, $requests, [
  199. 'concurrency' => 25,
  200. 'fulfilled' => function ($response, $index) {
  201. },
  202. 'rejected' => function ($reason, $index) {
  203. },
  204. ]);
  205. $promise = $pool->promise();
  206. $promise->wait();
  207. }
  208. }