ChannelClean.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. <?php
  2. /**
  3. * 渠道定期清理定时器脚本
  4. *
  5. */
  6. namespace app\crontab;
  7. set_time_limit(0);
  8. use think\console\Command;
  9. use think\console\Input;
  10. use think\console\Output;
  11. use think\Db;
  12. use app\common\logic\SubPackage as SubChannel;
  13. use app\common\logic\Log;
  14. use app\common\model\Setting;
  15. use app\common\model\Admin as AdminModel;
  16. use app\common\model\Channel;
  17. use app\common\model\SdkGameList;
  18. use app\common\model\PromotionShortLink;
  19. class ChannelClean extends Command {
  20. protected $old_max_channel_id = 23835; //历史渠道的最大渠道ID
  21. protected $now_time; //当前时间
  22. protected $_output;
  23. protected $sdkGameListModel;
  24. protected function configure() {
  25. $this->setName('ChannelClean')->setDescription('渠道定期清理脚本');
  26. }
  27. protected function execute(Input $input, Output $output) {
  28. ini_set('memory_limit', '1024M');
  29. $this->now_time = time();
  30. $this->_output = $output;
  31. $this->sdkGameListModel = new SdkGameList;
  32. $output->writeln(date('Y-m-d H:i:s')." ChannelClean start\r\n");
  33. $this->cleanNewChannel();
  34. $this->cleanOldChannel();
  35. $this->cleanGame();
  36. $output->writeln(date('Y-m-d H:i:s')." ChannelClean end\r\n");
  37. exit;
  38. }
  39. /**
  40. * 清理新创建渠道
  41. *
  42. */
  43. private function cleanNewChannel()
  44. {
  45. $settingModel = new Setting;
  46. $subChannel = new SubChannel;
  47. $adminModel = new AdminModel();
  48. $channelModel = new Channel;
  49. $this->_output->writeln(" cleanNewChannel\r\n");
  50. $day_limit = $settingModel::getSetting('NEW_CHANNEL_DAY');
  51. $channel_ids= []; //要清理的新增渠道
  52. //创建了几天以上的新渠道
  53. $adminList = $adminModel->field('channel_id')->where(['channel_id'=>['>',$this->old_max_channel_id]])->where(['status'=>1,'type'=>2,'create_time'=>['<',($this->now_time-$day_limit*24*3600)]])->select();
  54. $this->_output->writeln("cleanNewChannel----adminModel: ".$adminModel->getLastSql()." \r\n");
  55. if(!empty($adminList)){
  56. $channel_ids = arrayColumnByObject($adminList,'channel_id');
  57. }
  58. else{
  59. return false;
  60. }
  61. //有注册用户的渠道ID
  62. $activeRegitsterChannelIds = $this->getRegitsterChannelIds($day_limit);
  63. //有流水渠道
  64. $activePayChannelIds = $this->getPayChannelIds($day_limit);
  65. //活跃渠道
  66. $activeChannelIds = array_unique(array_merge($activeRegitsterChannelIds,$activePayChannelIds));
  67. //过滤掉有活跃用户的渠道ID
  68. $channel_ids = array_diff($channel_ids, $activeChannelIds);
  69. //过滤掉下级渠道有注册用户的渠道
  70. $channel_ids = $this->filterCleanNewChannel($channel_ids,$activeChannelIds);
  71. $sdkGameList = $this->sdkGameListModel->field('id,channel_id,gameid,package_type,filename')->where('channel_id',['in',$channel_ids],['>',$this->old_max_channel_id])->select();
  72. $this->_output->writeln("cleanNewChannel----sdkGameListModel: ".$this->sdkGameListModel->getLastSql()." \r\n");
  73. //要冻结的渠道
  74. $adminArr = $adminModel->field('id,channel_id,username')->where('channel_id',['in',$channel_ids],['>',$this->old_max_channel_id])->where(['status'=>1,'type'=>2])->select();
  75. $this->_output->writeln("cleanNewChannel----adminArr: ".$adminModel->getLastSql()." \r\n");
  76. // 启动事务
  77. Db::startTrans();
  78. try{
  79. //包体删除及分包记录删除
  80. if(!empty($sdkGameList)){
  81. foreach ($sdkGameList as $key => $value) {
  82. //删除包体文件
  83. $removeResult = $subChannel->removePackageFile($value['gameid'], $value['filename']);
  84. $this->sdkGameListModel->where(['id' => $value['id']])->delete();
  85. }
  86. }
  87. //冻结渠道
  88. if(!empty($adminArr)){
  89. foreach ($adminArr as $akey => $avalue) {
  90. $adminModel->where(['id' => $avalue['id'],'type'=>2])->update(['status'=>0]);
  91. $channelModel->where(['id' => $avalue['channel_id'],'flag'=>3])->update(['status'=>0]);
  92. Log::insertOperateLog('crontab/ChannelClean/cleanNewChannel', "编辑子渠道: {$avalue['username']},状态:冻结", 42, 1, 'admin');
  93. }
  94. }
  95. Db::commit();
  96. }
  97. catch (\Exception $e) {
  98. $this->_output->writeln(date('H:i:s')." 清理新创建渠道结果:fail".$e->getMessage()."\r\n");
  99. // 回滚事务
  100. Db::rollback();
  101. }
  102. }
  103. /**
  104. * 过滤掉下级渠道有活跃用户的渠道
  105. *
  106. * @param $channel_ids array 要冻结的渠道id
  107. * @param $activeChannelIds array 有活跃用户的渠道ID
  108. *
  109. */
  110. private function filterCleanNewChannel($channel_ids,$activeChannelIds)
  111. {
  112. $channelModel = new Channel;
  113. $result = [];
  114. if(!empty($channel_ids)){
  115. foreach($channel_ids as $id){
  116. //子渠道id
  117. $sub_channelIds = $channelModel->getChildIds($id);
  118. //有子渠道并且子渠道有活跃用户
  119. if(!empty($sub_channelIds) && !empty(array_intersect($sub_channelIds, $activeChannelIds))){
  120. }
  121. else{
  122. $result[] = $id;
  123. }
  124. }
  125. }
  126. return $result;
  127. }
  128. /**
  129. * 清理历史渠道
  130. *
  131. */
  132. private function cleanOldChannel()
  133. {
  134. $settingModel = new Setting;
  135. $subChannel = new SubChannel;
  136. $adminModel = new AdminModel();
  137. $this->_output->writeln(date('Y-m-d H:i:s')." cleanOldChannel \r\n");
  138. $day_limit = $settingModel::getSetting('OLD_CHANNEL_DAY');
  139. $activeRegitsterChannelIds = $this->getRegitsterChannelIds($day_limit); //有注册用户渠道
  140. $activePayChannelIds = $this->getPayChannelIds($day_limit); //有流水渠道
  141. $activeChannelIds = array_unique(array_merge($activeRegitsterChannelIds,$activePayChannelIds)); //活跃渠道
  142. $sdkGameList = $this->sdkGameListModel->field('id,channel_id,gameid,package_type,filename')
  143. ->where('channel_id',['not in',$activeChannelIds],['<=',$this->old_max_channel_id])
  144. ->where(['update_time'=>['<',($this->now_time-$day_limit*24*3600)]])->select();
  145. $this->_output->writeln(date('Y-m-d H:i:s')." cleanOldChannel----sdkGameListModel: ".$this->sdkGameListModel->getLastSql()." \r\n");
  146. //包体删除及分包记录删除
  147. if(!empty($sdkGameList)){
  148. foreach ($sdkGameList as $key => $value) {
  149. //删除包体文件
  150. $removeResult = $subChannel->removePackageFile($value['gameid'], $value['filename']);
  151. $this->sdkGameListModel->where(['id' => $value['id']])->delete();
  152. }
  153. }
  154. }
  155. /**
  156. * 清理下架的游戏
  157. *
  158. */
  159. private function cleanGame()
  160. {
  161. $settingModel = new Setting;
  162. $subChannel = new SubChannel;
  163. $shortLinkModel = new PromotionShortLink;
  164. $this->_output->writeln(date('Y-m-d H:i:s')." cleanGame\r\n");
  165. $day_limit = $settingModel::getSetting('GAME_DAY');
  166. //下架的游戏并且创建时间超过30天
  167. $game_list = Db::table('cy_game')->field('id,pinyin')->where(['cooperation_status'=>3,'create_time'=>['<',($this->now_time-$day_limit*24*3600)]])->select();
  168. //下架的游戏拼音数组
  169. $pinyin_list= [];
  170. //下架的游戏ID
  171. $game_ids = [];
  172. if (!empty($game_list)) {
  173. foreach ($game_list as $gvalue) {
  174. $game_ids[] = $gvalue['id'];
  175. $pinyin_list[$gvalue['id']] = $gvalue['pinyin'];
  176. }
  177. }
  178. else{
  179. return false;
  180. }
  181. //------------------- 指定时间内有流水的下架游戏 start ------------------------//
  182. $pay_gameids = Db::table('cy_pay force index(idx_status_createtime)')->field('DISTINCT gameid')->where(['status'=>1,'create_time'=>['>=',($this->now_time-$day_limit*24*3600)],'gameid'=>['in',$game_ids]])->select();
  183. if(!empty($pay_gameids)){
  184. $pay_gameids = arrayColumnByObject($pay_gameids,'gameid');
  185. //过滤掉有流水的下架游戏
  186. $game_ids = array_diff($game_ids, $pay_gameids);
  187. }
  188. //------------------- 指定时间内有流水的下架游戏 end ------------------------//
  189. //------------------- 指定时间内有登录用户的下架游戏 start ------------------------//
  190. //指定天数的前半部分
  191. $day_before_limit= (int)($day_limit/2);
  192. //指定时间内有登录用户的下架游戏ID
  193. $login_before_gameids = Db::table('cy_logininfo')->field('DISTINCT gameid')
  194. ->where("login_time>=".($this->now_time-$day_limit*24*3600)." and login_time<".($this->now_time-$day_before_limit*24*3600))
  195. ->where(['gameid'=>['in',$game_ids]])->select();
  196. if(!empty($login_before_gameids)){
  197. $login_before_gameids = arrayColumnByObject($login_before_gameids,'gameid');
  198. //过滤掉有登录用户的下架游戏
  199. $game_ids = array_diff($game_ids, $login_before_gameids);
  200. }
  201. //指定时间内有登录用户的下架游戏ID
  202. $login_after_gameids = Db::table('cy_logininfo')->field('DISTINCT gameid')
  203. ->where("login_time>=".($this->now_time-$day_before_limit*24*3600))
  204. ->where(['gameid'=>['in',$game_ids]])->select();
  205. if(!empty($login_after_gameids)){
  206. $login_after_gameids = arrayColumnByObject($login_after_gameids,'gameid');
  207. //过滤掉有登录用户的下架游戏
  208. $game_ids = array_diff($game_ids, $login_after_gameids);
  209. }
  210. //------------------- 指定时间内有登录用户的下架游戏 end ------------------------//
  211. $sdkGameList = $this->sdkGameListModel->field('id,channel_id,gameid,package_type,filename')->where(['gameid'=>['in',$game_ids]])->select();
  212. //删除推广落地页的短链接记录
  213. $shortLinkModel->where(['game_id'=>['in',$game_ids]])->delete();
  214. $this->_output->writeln("cleanGame----sdkGameListModel: ".$this->sdkGameListModel->getLastSql()." \r\n");
  215. //包体删除及分包记录删除
  216. if(!empty($sdkGameList)){
  217. foreach ($sdkGameList as $key => $value) {
  218. //删除包体文件
  219. $subChannel->removePackageFile($value['gameid'], $value['filename']);
  220. $this->sdkGameListModel->where(['id' => $value['id']])->delete();
  221. }
  222. }
  223. //删除游戏母包
  224. if (!empty($game_ids)) {
  225. foreach ($game_ids as $gid) {
  226. $path = '/data/www/aoyou/download/sygame/'.$pinyin_list[$gid];
  227. //文件夹是否存在,并且是个目录
  228. if (is_dir($path)) {
  229. $this->_output->writeln("cleanGame----删除游戏母包: ".$path." \r\n");
  230. $matches = glob($path . '/*');
  231. if (is_array($matches)) {
  232. array_map('unlink', $matches);
  233. }
  234. rmdir($path);
  235. }
  236. }
  237. }
  238. }
  239. /**
  240. * 获得指定时间内有注册玩家的渠道ID
  241. *
  242. * @param $day_limit int 指定的天数
  243. *
  244. * @return $channel_ids array 渠道ID集
  245. */
  246. private function getRegitsterChannelIds($day_limit)
  247. {
  248. $settingModel = new Setting;
  249. $channel_ids = [];
  250. for($i=1;$i<=$day_limit;$i++){
  251. $temp_ids = Db::table('cy_member_channel_game_rel')->field('DISTINCT channel_id')->where("mcgr_createtime>=".($this->now_time-$i*24*3600)." and mcgr_createtime<".($this->now_time-($i-1)*24*3600))->select();
  252. //$this->_output->writeln(" getRegitsterChannelIds:".Db::table('cy_member_channel_game_rel')->getLastSql()."\r\n");
  253. $temp_ids = !empty($temp_ids) ? arrayColumnByObject($temp_ids,'channel_id') : [];
  254. $channel_ids = array_unique(array_merge($channel_ids,$temp_ids));
  255. }
  256. //白名单
  257. $channel_white_list = $settingModel::getSetting('CHANNEL_WHITE_LIST');
  258. if(!empty($channel_white_list)){
  259. $channel_white_list = explode(",", $channel_white_list);
  260. $channel_ids = array_unique(array_merge($channel_ids,$channel_white_list));
  261. }
  262. return $channel_ids;
  263. }
  264. /**
  265. * 获得指定时间内有流水的渠道ID
  266. *
  267. * @param $day_limit int 指定的天数
  268. *
  269. * @return $channel_ids array 渠道ID集
  270. *
  271. */
  272. private function getPayChannelIds($day_limit)
  273. {
  274. $channel_ids = [];
  275. for($i=1;$i<=$day_limit;$i++){
  276. $temp_ids = Db::table('cy_pay')->field('DISTINCT channel_id')->where("create_time>=".($this->now_time-$i*24*3600)." and create_time<".($this->now_time-($i-1)*24*3600))->where(['status'=>1])->select();
  277. //$this->_output->writeln(" getPayChannelIds:".Db::table('cy_pay')->getLastSql()."\r\n");
  278. $temp_ids = !empty($temp_ids) ? arrayColumnByObject($temp_ids,'channel_id') : [];
  279. $channel_ids = array_unique(array_merge($channel_ids,$temp_ids));
  280. }
  281. return $channel_ids;
  282. }
  283. }