send(); } private function generateRequest() { $switch_array = []; $now_hour = date('G'); $temp = 0; $info = DB::connection('api_mysql')->table('custom_msg_switchs')->where('custom_category','continue_read')->first(); if(!$info) return ; $default_status = $info->default_switch_status; while (true){ $user = DB::connection('api_mysql')->table('temp_force_subscribe_users') ->select('id','uid','distribution_channel_id','openid','appid') ->where('id','>',$temp) //->whereIn('id',[3032288,3042985]) ->where('last_interactive_time','>',date('Y-m-d H:i:s',time()-86400*2)) ->orderBy('id') ->limit(1000) ->get(); if(!$user) break; foreach ($user as $item){ if(isInnerSites($item->distribution_channel_id)) continue; //if(!in_array($item->distribution_channel_id,[70])) continue; //\Log::info( '---------------------------start--start-------------------------------------------' ); //\Log::info('$item->distribution_channel_id is :'.$item->distribution_channel_id ); //\Log::info( '$item->id is :'.$item->id ); if(!isset($switch_array[$item->distribution_channel_id])){ $switch = DB::connection('api_mysql')->table('custom_msg_switchs_msgs') ->where('distribution_channel_id',$item->distribution_channel_id) ->where('custom_category','continue_read') ->select('status') ->first(); if($switch){ $switch_array[$item->distribution_channel_id] = $switch->status; }else{ $switch_array[$item->distribution_channel_id] = $default_status; } } $switch_status = $switch_array[$item->distribution_channel_id]; //if(!in_array($item->distribution_channel_id,[5,123,14,13,8])) continue; if($switch_status != 1) continue; //\Log::info( '$item->distribution_channel_id in is :'.$item->distribution_channel_id ); //$data = ['first'=>[],'seconds'=>[]]; $read_info = $this->getReadRecord($item->uid); if(empty($read_info['first'])){ continue; } //获取本次发送的时间间隔 $this_push_hour = Redis::hget('book_read:'.$item->uid,'next_push_hour'); //上次发送时间 $prev_send_info = DB::connection('api_mysql')->table('custom_push_keep_continue')->where('uid',$item->uid)->select('send_time')->orderBy('id','desc')->first(); $diff = $this_push_hour?$this_push_hour:8; if($diff == 8){ if((time()-$read_info['time']) > 3600*8){ $send_hour = $now_hour; }else{ $send_hour = -1; } }else{ if($prev_send_info){ //$send_hour = date('G',strtotime($prev_send_info->send_time)+$diff*3600); if((time()-strtotime($prev_send_info->send_time)) >$diff*3600){ $send_hour = $now_hour; }else{ $send_hour = -1; } }else{ $send_hour = $now_hour; } } $domain = sprintf('https://site%s.%s.com',encodeDistributionChannelId($item->distribution_channel_id), env('CUSTOM_HOST')); if($send_hour != $now_hour ) continue; $openid = $item->openid; $appid = $item->appid; $user_info = DB::connection('api_mysql')->table('users')->where('id',$item->uid)->select('nickname')->first(); $nickname = '读者'; if($user_info && $user_info->nickname)$nickname = $user_info->nickname; //$content_format = "您看的小说有更新\r\n\r\n《%s》剧情已更新,点击继续阅读 \r\n\r\n记得点击菜单栏签到领书币哦"; $content_format = "@%s 为您推荐上次未看完的小说\r\n\r\n点击继续阅读❤\r\n\r\n"; /*$content = sprintf($content_format, sprintf($continueReadUrlFormat, encodeDistributionChannelId($item->distribution_channel_id), env('CUSTOM_HOST'), $read_info['url'] ), $read_info['book_name'] )*/; $content = sprintf($content_format,$nickname,$domain.$read_info['first']['url']); if(!empty($read_info['seconds'])){ $content .= "历史阅读记录:\r\n\r\n"; foreach ($read_info['seconds'] as $record_item){ $content .= sprintf(" 🌳 %s\r\n",$domain.$record_item['url'],$record_item['book_name']); } } $content .= "\r\n为了方便下次阅读,请置顶公众号"; $access_token = $this->getAccessToken($appid); if(!$access_token)continue; $url = 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token='.$access_token; $request = new GuzzleRequest('post',$url,[],\GuzzleHttp\json_encode([ 'touser'=>$openid, 'msgtype'=>'text', 'text'=>['content'=>$content] ],JSON_UNESCAPED_UNICODE)); DB::connection('api_mysql')->table('custom_push_keep_continue')->insert([ 'uid'=>$item->uid, 'time_diff'=>$diff, 'send_time'=>date('Y-m-d H:i:s'), 'day'=>date('Y-m-d'), 'created_at'=>date('Y-m-d H:i:s'), 'updated_at'=>date('Y-m-d H:i:s') ]); if($diff == 8){ $next = 24; }else{ $next = 24; } Redis::hset('book_read:'.$item->uid,'next_push_hour',$next); //\Log::info( '----------------------------end-end-end-------------------------------------------' ); yield $request; } $temp = $item->id; } } private function getFirstReadRecord($uid){ //Redis::hget('book_base:' . $uid, 'last_read', "{$bid}_{$cid}_{$book_name}_{$chapter_name}_" . time()); $record = Redis::hget('book_read:' . $uid, 'last_read'); if($record){ $record_arr = explode('_',$record); $bid = $record_arr[0]; $book_name = $this->bid2BookName($bid); //$hash = new Hashids('D6M97LIvpp4qWuz3nKzqi6yYN4GAA61b',32,'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'); $bid = $hash->encode($bid); $cid = $record_arr[1]; $time = $record_arr[2]; $res = [ 'url' => '/reader?bid='.$bid.'&cid='.$cid.'&fromtype=continue_read', 'book_name'=>$book_name, 'bid'=>$bid, 'time'=>$time ]; return $res; } return []; } private function getReadRecord($uid){ //$hash = new Hashids('D6M97LIvpp4qWuz3nKzqi6yYN4GAA61b',32,'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'); $records = Redis::hgetall('book_read:' . $uid); $data = ['first'=>[],'seconds'=>[],'time'=>'']; foreach ($records as $k=>$item){ if($k == 'last_read'){ $record_arr = explode('_',$item); $bid = $record_arr[0]; //$book_name = $this->bid2BookName($bid); $bid = Hashids::encode($bid); $cid = $record_arr[1]; $time = $record_arr[2]; $data['first'] = [ 'url' => '/reader?bid='.$bid.'&cid='.$cid.'&fromtype=continue_read', 'book_name'=>'', ]; $data['time'] = $time; continue; } if(!is_numeric($k)) continue; $record = explode('_', $item); $latest_read_cid = $record[0]; $book_name = self::bid2BookName($k); $latest_read_time = $record[count($record) - 1]; $data['seconds'][] =[ 'url' => '/reader?bid='.Hashids::encode($k).'&cid='.$latest_read_cid.'&fromtype=continue_read', 'book_name'=>$book_name, 'time'=>$latest_read_time ]; } $temp = $data['seconds']; if($temp){ usort($temp, function ($a, $b) { if ($a['time'] >= $b['time']) return -1; return 1; }); } $temp_res = []; foreach ($temp as $k=>$it){ $temp_res[] = $it; if($k>=2) break; } $data['seconds'] = $temp_res; return $data; } private function bid2BookName($bid){ $book_name = null; if(is_null($book_name)){ $book_key = 'wap:string:book:'.$bid; $book_name = Redis::get($book_key); Redis::EXPIRE($book_key,3600); if(!$book_name){ $book_name = ''; $book_info = DB::connection('api_mysql')->table('book_configs')->where('bid',$bid)->select('book_name')->first(); //$book_info = BookConfigService::getBookById($bid); if($book_info && isset($book_info->book_name)){ $book_name = $book_info->book_name; Redis::setex($book_key,3600,$book_name); } } } return $book_name; } private function getAccessToken($appid){ try{ $WechatController = new WechatController($appid); $accessToken = $WechatController->app->access_token; // EasyWeChat\Core\AccessToken 实例 $token = $accessToken->getToken(); // token 字符串 return $token; }catch(\Exception $e){ \Log::error($e->getMessage()); } return ''; } private function send(){ $client = new Client(); $requests = $this->generateRequest(); $pool = new Pool($client, $requests, [ 'concurrency' => 5, 'fulfilled' => function ($response, $index) { }, 'rejected' => function ($reason, $index) { }, ]); $promise = $pool->promise(); $promise->wait(); } }