控制台应用,yzncms本身基于tp5.1框架,里面的队列用不了,bug,坑
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Ai.php 28KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | Yzncms [ 御宅男工作室 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2018 http://yzncms.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | fastadmin: https://www.fastadmin.net/
  10. // +----------------------------------------------------------------------
  11. // +----------------------------------------------------------------------
  12. // | 邮箱验证码接口
  13. // +----------------------------------------------------------------------
  14. namespace app\api\controller;
  15. use app\member\controller\MemberApi;
  16. use think\Db;
  17. /**
  18. * @title 邮箱验证码接口
  19. * @controller api\controller\Ems
  20. * @group base
  21. */
  22. class Ai extends MemberApi
  23. {
  24. protected $noNeedLogin = ['login', 'register','uploadCsv','uploadCsvFrom','exportCsv','dsTitle','dsTitlelist','dsTitle13','bdPicHandle'];
  25. protected $noNeedRight = [];
  26. //初始化
  27. protected function initialize()
  28. {
  29. //yzncms本身已经做了跨域处理 妈的
  30. //$this->getHook();
  31. parent::initialize();
  32. }
  33. public static function getHook()
  34. {
  35. //需要使用静态方法Facade 不然会报错
  36. \think\Facade\Hook::listen('response_send');
  37. }
  38. /*
  39. * 业务控制器
  40. * 上传csv关键词数据
  41. * https://console.zx2049.com/api/ai/uploadCsv?file=20240504/eebcb4ca6a8a69fdd9e0f60c16b55746.csv
  42. */
  43. public function uploadCsv(){
  44. //测试
  45. $url = request()->get('file',0);
  46. if($url !== 0){
  47. $this->csvHandle('./uploads/'.$url);
  48. return json([]);
  49. }
  50. $file = request()->file('file'); //$file = $_FILES['file'];
  51. $info = $file->move( './uploads');
  52. if($info){
  53. // 成功上传后 获取上传信息
  54. // 输出 jpg
  55. //$url = $info->getExtension();
  56. // 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
  57. $url = $info->getSaveName();
  58. // 输出 42a79759f284b767dfcb2a0197904287.jpg
  59. //echo $info->getFilename();
  60. $data = ['code' => 0, 'msg' => '文件上传成功', 'data' =>['src'=>$url]];
  61. }else{
  62. // 上传失败获取错误信息
  63. $info = $file->getError();
  64. $data = ['code' => 1, 'msg' => '文件上传失败', 'data' =>$info];
  65. }
  66. return json($data);
  67. }
  68. /*
  69. * 业务控制器
  70. * 处理表单
  71. */
  72. public function uploadCsvFrom(){
  73. $post = request()->post();
  74. /*
  75. * rule:
  76. 0
  77. title:
  78. 建筑职称
  79. file:
  80. url:
  81. 20240505/2aff80b14c861480183278bbc9442f56.csv
  82. */
  83. //判断关键词是否存在
  84. $one = Db::name('options')->where('title','=',$post['title'])->where('status','=',1)->find();
  85. if(empty($one)){
  86. $data = ['code' => 1, 'msg' => '关键词不存在', 'data' => []];
  87. return json($data);
  88. }
  89. if(!empty($post['url'])){
  90. $this->csvHandle('./uploads/'.$post['url'],$post['rule'],$post['title']);
  91. $data = ['code' => 0, 'msg' => '提交成功', 'data' =>$post];
  92. }else{
  93. $data = ['code' => 1, 'msg' => '提交失败', 'data' => []];
  94. }
  95. return json($data);
  96. }
  97. /*
  98. * 逻辑控制器
  99. * 规则的指令集和创意 如果为空 调用全局的即可 同样优先调用自身规则
  100. */
  101. public function csvHandle($url,$rule,$title){
  102. // 读取CSV文件
  103. $filename = $url;
  104. if (file_exists($filename)) {
  105. $file = fopen($filename, 'r');
  106. //任务批次
  107. $task_no = date('YmdHis',time()).'-'.rand(1,10000);
  108. //插入 重复也无所谓了
  109. Db::name('pc')->insert(['catid'=>31,'title'=>$task_no,'create_time' => time(),'update_time' => time()]);
  110. $pid = time(); //不考虑并发提交多次间隔也是秒级
  111. $num = 1;
  112. $log_content = '';
  113. $log_content_error = '';
  114. $s_num = 0;
  115. $f_num = 0;
  116. while (($line = fgetcsv($file)) !== FALSE) {
  117. // $line是一个数组,包含CSV的一行数据
  118. //print_r($line);
  119. if($num === 1){
  120. $row = $line;
  121. }else{
  122. if(!empty($line[0])) {
  123. //关键词步骤省略 需要去站长之家搜索并导出 这个步骤由人工操作
  124. //判断是否存在短标题 重复性检测
  125. //相同规则 短标题只能存在一个
  126. $one = Db::name('cms_zl')
  127. ->where('title', '=', $line[0])
  128. ->where('catid', '=', 18) //分类id
  129. ->where('zc', '=', $title) //主词
  130. ->where('gzxh', '=', $rule) //规则id
  131. ->where('sj','=',$task_no) //时间维度 批次
  132. ->find();
  133. if (empty($one)) {
  134. //过滤标题是否合法的函数 这个可以用定时任务处理
  135. [$is_use, $desc, $rule_id] = $this->titleHandle($line[0], $rule, $title);
  136. //构建详情
  137. $html = '';
  138. for ($i = 1; $i < 10; $i++) {
  139. $html .= $row[$i] . ':' . $line[$i] . '<br/>';
  140. }
  141. $data = [
  142. 'catid' => 18, //短标题
  143. 'title' => $line[0], //短标题
  144. 'content' => $html,
  145. 'zc' => $title, //增加主词字段
  146. 'create_time' => time(),
  147. 'update_time' => time(),
  148. 'status' => 0, //默认禁用状态 定时手动开启 自动化再读取即可
  149. 'pid' => $pid, //关联日志的aid,可查询到规则序号 主词 文件地址 执行情况
  150. 'ptlx' => 0,
  151. 'is_use' => $is_use, //是否合法
  152. 'desc' => $desc, //非法原因 或者 合法匹配结果
  153. 'gzxh' => $rule,
  154. 'sj' => $task_no, //写入时间维度 批次
  155. 'is_use_id' => json_encode($rule_id,JSON_UNESCAPED_UNICODE), //写入具体规则id 可查询到对应规则是什么 判断是否合法
  156. ];
  157. //dump($data);
  158. //插入记录
  159. $doc_id = Db::name('cms_zl')->insertGetId($data);
  160. //写入日志
  161. $log_content .= '指令id-' . $doc_id . '-' . json_encode($line, JSON_UNESCAPED_UNICODE) . '<br/>';
  162. $s_num++;
  163. //通知前端
  164. $is_use_desc = $is_use === 1?'合法':'不匹配';
  165. $msg = [
  166. 'info' => '['.$line[0].']成功新增记录!匹配结果:'.$is_use_desc
  167. ];
  168. $this->curlPost($msg);
  169. } else {
  170. //写日志
  171. $log_content_error .= '<p>短标题-' . $line[0] . '-已存在-指令短标题id:' . $one['id'] . '</p>';
  172. $f_num++;
  173. //通知前端
  174. $msg = [
  175. 'info' => '相同规则与相同主词下,['.$line[0].']已存在-不可重复导入!'
  176. ];
  177. $this->curlPost($msg);
  178. }
  179. }
  180. }
  181. $num++;
  182. }
  183. //每次操作 1-2条 日志记录
  184. if(!empty($log_content)){
  185. Db::name('log')->insert([
  186. 'catid' => 27,
  187. 'title' => '批次'.$task_no.'成功导入处理-'.$s_num.'条数据',
  188. 'keywords' => $title, //主词
  189. 'description' => $filename,//对应文件地址
  190. 'create_time' => time(),
  191. 'update_time' => time(),
  192. 'status' => 1,
  193. 'site_id'=> 1,
  194. 'cid' => (int)$rule, //规则序号
  195. 'aid' => $pid, //对应记录id
  196. 'content' => '<p>'.$log_content.'</p>',
  197. ]);
  198. }
  199. if(!empty($log_content_error)){
  200. Db::name('log')->insert([
  201. 'catid' => 27,
  202. 'title' => '批次'.$task_no.'导入处理已存在-'.$f_num.'条数据',
  203. 'keywords' => $title, //主词
  204. 'description' => $filename,//对应文件地址
  205. 'create_time' => time(),
  206. 'update_time' => time(),
  207. 'status' => 1,
  208. 'site_id'=> 1,
  209. 'cid' => (int)$rule, //规则序号
  210. 'aid' => $pid, //对应记录id
  211. 'content' => '<p>'.$log_content_error.'</p>',
  212. ]);
  213. }
  214. fclose($file);
  215. }
  216. /*// 写入CSV文件
  217. $data = [
  218. ['Name', 'Age', 'Email'],
  219. ['Alice', 25, 'alice@example.com'],
  220. ['Bob', 30, 'bob@example.com']
  221. ];
  222. $filename = 'output.csv';
  223. $file = fopen($filename, 'w');
  224. foreach ($data as $row) {
  225. fputcsv($file, $row);
  226. }
  227. fclose($file);*/
  228. }
  229. /*
  230. * 模型控制器 操作数据
  231. */
  232. /*
  233. * 处理函数
  234. * $title 主词
  235. */
  236. public function titleHandle($line,$rule,$title){
  237. //规则1
  238. $desc = '';
  239. //是否完全匹配主词
  240. if (strpos($line, $title) !== false) {
  241. //包含主词
  242. }else{
  243. return [0,'短标题不包含主词['.$title.']',0];
  244. }
  245. //1.查询是否存在主词规则
  246. $one = Db::name('cms_zl')
  247. ->where('catid','=',17)
  248. ->where('title','=',$title) //只能一条 已做标题重复校验
  249. ->where('is_qj','=',0) //非全局
  250. ->where('zllx','=',1) //指令类型是 主词
  251. ->where('gzxh','=',$rule)
  252. ->where('status','=',1) //多条需要控制开关
  253. ->order('id asc') //可能添加多条 以第一条为主 理论每个规则只添加一条
  254. ->find();
  255. //2.查询全局主词规则
  256. if(empty($one)){
  257. $one = Db::name('cms_zl')
  258. ->where('catid','=',17)
  259. ->where('title','=','全局-主词类型') //只能一条 已做标题重复校验
  260. ->where('is_qj','=',1) //是全局
  261. ->where('zllx','=',1) //指令类型是 主词
  262. ->where('gzxh','=',$rule)
  263. ->where('status','=',1) //多条需要控制开关
  264. ->order('id asc') //可能添加多条 以第一条为主 理论每个规则只添加一条
  265. ->find();
  266. }
  267. //3.查询全局规则
  268. if(empty($one)){
  269. $one = Db::name('cms_zl')
  270. ->where('catid','=',17)
  271. ->where('title','=','全局-非主非副') //只能一条 已做标题重复校验
  272. ->where('is_qj','=',1) //是全局
  273. ->where('zllx','=',0) //指令类型是 非主非副
  274. ->where('gzxh','=',$rule)
  275. ->where('status','=',1) //多条需要控制开关
  276. ->order('id asc') //可能添加多条 以第一条为主 理论每个规则只添加一条
  277. ->find();
  278. }
  279. if(empty($one)){
  280. return [0,'不存在全局通用规则,全局主词规则,当前主词规则',0];
  281. }
  282. //4.获取到全局或主词的副词
  283. $two = [];
  284. if(empty($one['fclb']) || (string)$one['fclb'] === '0'){
  285. //不存在副词规则 快照 表示这条规则 没有副词匹配要求
  286. //即使标题里面存在 主词设置的副词列表
  287. //即使存在某些副词规则 不存在副词规则 确定不了哪个是副词 故二无法匹配
  288. $desc .= '不存在副词规则-|-';
  289. }else{
  290. //存在副词规则
  291. $one['fclb'] = $one['fclb'].',';
  292. $fclb = explode(',',$one['fclb']);
  293. $line_sor = str_replace($title, "", $line); //短标题去除主词
  294. $is_bh = 0;
  295. $fc = '';
  296. $fc_num = 0;
  297. foreach ($fclb as $k => $v) {
  298. //该判断 主词和副词 不一定是连在一起的
  299. if(!empty($v)) {
  300. if (strpos($line_sor, $v) !== false) {
  301. //包含
  302. $is_bh = 1;
  303. $fc = $v;
  304. //break; //跳出 目前只匹配一个 存在多个不做处理 以第一个为主
  305. $fc_num++;
  306. }
  307. }
  308. }
  309. //如果副词快照存在,那么以副词快照里面找不到,那么再去找主词设置是否存在
  310. //这样判断是不真实的 因为主词设置是会修改的
  311. if($is_bh === 0){
  312. //$fc 无法确认值 所以无法匹配副词规则
  313. //当主词规则 都没有填写副词列表 就表示不匹配副词了
  314. }
  315. //存在多个副词 不合理
  316. if($fc_num > 1){
  317. return [0,'存在多个副词,不合法',$one['id']];
  318. }
  319. //5.判断是否存在副词
  320. if($is_bh === 1){
  321. //6.查询主词+副词是否存在规则
  322. $two = Db::name('cms_zl')
  323. ->where('catid','=',17)
  324. ->where('title','=',$title.$fc) //查询设置 按照主词+副词 格式查询 //只能一条 已做标题重复校验
  325. ->where('is_qj','=',0) //非全局
  326. ->where('zllx','=',2) //指令类型是 副词
  327. ->where('gzxh','=',$rule)
  328. ->where('status','=',1) //多条需要控制开关
  329. ->order('id asc') //可能添加多条 以第一条为主 理论每个规则只添加一条
  330. ->find();
  331. //7.查询副词通用全局规则
  332. if(empty($two)){
  333. $two = Db::name('cms_zl')
  334. ->where('catid','=',17)
  335. ->where('title','=','全局-副词类型') //查询设置 按照主词+副词 格式查询 //只能一条 已做标题重复校验
  336. ->where('is_qj','=',1) //非全局
  337. ->where('zllx','=',2) //指令类型是 副词
  338. ->where('gzxh','=',$rule)
  339. ->where('status','=',1) //多条需要控制开关
  340. ->order('id asc') //可能添加多条 以第一条为主 理论每个规则只添加一条
  341. ->find();
  342. }
  343. }else{
  344. //短标题不包含副词
  345. $desc .= '短标题不包含副词-|-';
  346. }
  347. }
  348. //短标题的主词和副词 不一定是连在一起的
  349. if(!empty($two)){
  350. //存在副词规则 按照此规则执行
  351. $data = $two;
  352. }else{
  353. //按照$one规则记录执行
  354. $data = $one;
  355. }
  356. //8.判断是否合法 地区词
  357. [$is_bh,$fc] = $this->isInRule($data['dqc'],$line);
  358. if($is_bh > 0){
  359. $desc .= '存在地区词'.$fc.',不合法-|-';
  360. return [0,$desc,$data];
  361. }
  362. //9.判断是否合法 分类词
  363. [$is_bh,$fc] = $this->isInRule($data['flc'],$line);
  364. if($is_bh > 0){
  365. $desc .= '存在分类词'.$fc.',不合法-|-';
  366. return [0,$desc,$data];
  367. }
  368. //10.判断是否合法 时间词
  369. [$is_bh,$fc] = $this->isInRule($data['sjc'],$line);
  370. if($is_bh > 0){
  371. $desc .= '存在时间词'.$fc.',不合法-|-';
  372. return [0,$desc,$data];
  373. }
  374. //11.判断是否合法 屏蔽词
  375. [$is_bh,$fc] = $this->isInRule($data['pbc'],$line);
  376. if($is_bh > 0){
  377. $desc .= '存在屏蔽词'.$fc.',不合法-|-';
  378. return [0,$desc,$data];
  379. }
  380. //12.替换指令的变量
  381. //var_dump($data['zlj']);die;
  382. if(!empty($data['zlj'])){
  383. $zlj = json_decode($data['zlj'],true);
  384. $zlj_new = [];
  385. foreach ($zlj as $k => $v) {
  386. $key = ''.(string)$k.'';
  387. if (strpos($v,'K') !== false) {
  388. $v_str = str_replace("K", $line, $v);
  389. $zlj_new[$key] = $v_str;
  390. }else{
  391. $zlj_new[$key] = $v;
  392. }
  393. }
  394. $zlj_new_json = json_encode($zlj_new,JSON_UNESCAPED_UNICODE);
  395. $data['zlj'] = $zlj_new_json;
  396. //var_dump($zlj_new_json);die;
  397. }
  398. //13.判断是否合法 同时存在触发词和并发词
  399. //增加判断可以不存在并发词和触发词
  400. //只需要匹配 包含主词即可通过
  401. if(!empty($data['cfc']) && (string)$data['cfc'] != '0' || !empty($data['bfc']) && (string)$data['bfc'] != '0'){
  402. [$is_bh1,$fc1] = $this->isInRule($data['cfc'],$line);
  403. [$is_bh2,$fc2] = $this->isInRule($data['bfc'],$line);
  404. }else{
  405. $desc .= '不需要验证并发词和触发词,合法';
  406. return [1,$desc,$data];
  407. }
  408. if($is_bh1 > 0 && $is_bh2 > 0){
  409. //同时存在
  410. $desc .= '合法,同时存在并发词['.$fc2.']和触发词['.$fc1.']';
  411. return [1,$desc,$data];
  412. }else if($is_bh1 > 0 || $is_bh2 > 0){
  413. $desc .= '合法,不同时存在并发词['.$fc2.']和触发词['.$fc1.']';
  414. return [1,$desc,$data];
  415. }else{
  416. $desc .= '不合法,同时不存在并发词['.$fc2.']和触发词['.$fc1.']';
  417. return [0,$desc,$data];
  418. }
  419. }
  420. /*
  421. * 规则设定
  422. */
  423. public function setRule(){
  424. //方案1: 定义config配置文件
  425. //方案2: 直接代码写死
  426. //方案3: 后台设置 -- 采用这个
  427. $json = [
  428. ''
  429. ];
  430. }
  431. /*
  432. * 函数 是否包含
  433. */
  434. public function isInRule($data,$str){
  435. $data = $data.',';
  436. $data = explode(',',$data);
  437. $is_bh = 0;
  438. $fc = '';
  439. foreach ($data as $k => $v) {
  440. //该判断 主词和副词 不一定是连在一起的
  441. if(!empty($v)) {
  442. if (strpos($str, $v) !== false) {
  443. //包含
  444. $is_bh = 1;
  445. $fc = $v;
  446. break; //跳出 目前只匹配一个 存在多个不做处理 以第一个为主
  447. }
  448. }
  449. }
  450. return [$is_bh,$fc];
  451. }
  452. /*
  453. * 导出csv
  454. * http://console.zx2049.com/api/ai/exportCsv
  455. */
  456. public function exportCsv(){
  457. $list = Db::name('cms_zl')->field('id,title,desc')->where('catid','=',18)->select();
  458. /* $data = [
  459. ['Name', 'Age', 'Email'],
  460. ['Alice', 25, 'alice@example.com'],
  461. ['Bob', 30, 'bob@example.com']
  462. ];*/
  463. $filename = 'output.csv';
  464. $file = fopen($filename, 'w');
  465. foreach ($list as $row) {
  466. fputcsv($file, $row);
  467. }
  468. fclose($file);
  469. //执行下载
  470. }
  471. /*
  472. * curl - post 通知
  473. */
  474. public function curlPost($data){
  475. $ch = curl_init();
  476. curl_setopt($ch, CURLOPT_URL, "http://workerman.dev.zx2049.com/work/push/test");
  477. curl_setopt($ch, CURLOPT_POST, 1);
  478. //The number of seconds to wait while trying to connect. Use 0 to wait indefinitely.
  479. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
  480. curl_setopt($ch, CURLOPT_POSTFIELDS , http_build_query($data));
  481. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  482. $output = curl_exec($ch);
  483. curl_close($ch);
  484. return $output;
  485. }
  486. /*
  487. * 定时自动通过合法的短标题
  488. * http://console.zx2049.com/api/ai/dsTitle
  489. */
  490. public function dsTitle()
  491. {
  492. $id_list = Db::name('cms_zl')->where([
  493. 'catid'=>18,
  494. 'is_use' => 1,
  495. 'status' => 0
  496. ])->limit(10)->column('id');
  497. dump($id_list);
  498. Db::name('cms_zl')->where('id','in',$id_list)->update([
  499. 'status' => 1
  500. ]);
  501. }
  502. /*
  503. * 定时同步通过审核的短标题到自动发文
  504. * http://console.zx2049.com/api/ai/dsTitlelist
  505. * 必须判断唯一 如果标题一样 就不写入了
  506. */
  507. public function dsTitlelist()
  508. {
  509. //得到最后时间
  510. $row = Db::name('cms_ai')->where([
  511. 'catid' => 13
  512. ])
  513. ->order('tb_time desc')
  514. ->limit(1)
  515. ->find();
  516. //var_dump($row);
  517. if(isset($row['tb_time'])){
  518. $lasttime = $row['tb_time'];
  519. }else{
  520. $lasttime = 0;
  521. }
  522. $list = Db::name('cms_zl')->where([
  523. 'catid'=>18,
  524. 'is_use' => 1, //合法
  525. 'status' => 1,
  526. 'is_cf' => 0, //是否重复
  527. //'id'=>1199
  528. ])
  529. ->field('id,title,create_time,is_use_id')
  530. ->where('create_time','>',$lasttime)
  531. //->limit(10) //不能限制数量 不然时间查询 下次会漏掉某些时间相同的剩余数量 //要么使用状态字段 //要么使用自增id判断
  532. ->order('create_time asc') //必须asc排序 先入库
  533. ->select();
  534. //dump($list);die;
  535. foreach ($list as $index=>$row) {
  536. $one = Db::name('cms_ai')->field('id,title')->where(['catid' => 13])->where('title','=',$row['title'])->find();
  537. if(empty($one)){
  538. //$json = strip_tags(htmlspecialchars_decode($row['is_use_id']));
  539. //echo $json;
  540. $json = $row['is_use_id'];
  541. $json = json_decode($json,true);
  542. //dump($json);die;
  543. //读取指令集
  544. $zlj = $json['zlj'];
  545. $zlj_arr = json_decode($zlj,true);
  546. $zlj_end = end($zlj_arr);
  547. $key = count($zlj_arr)-1;
  548. unset($zlj_arr[$key]);
  549. $zlj = json_encode($zlj_arr,JSON_UNESCAPED_UNICODE);
  550. //获取创意
  551. if((string)$json['is_sj'] === '-1'){
  552. //不需要加创意
  553. $cy = '0';
  554. }else{
  555. if((int)$json['is_sj'] > 0){
  556. //既然指定 不管管是否为空
  557. $cy = $json['cy'.$json['is_sj']];
  558. }else{
  559. //随机
  560. $sj_num = [];
  561. for($i=1;$i<=6;$i++){
  562. if(!empty($json['cy'.$i])){
  563. $sj_num[] = $i;
  564. }
  565. }
  566. if(!empty($sj_num)){
  567. $randomKey = array_rand($sj_num);
  568. $num = $sj_num[$randomKey];
  569. $cy = $json['cy'.$num];
  570. }else{
  571. $cy = '0';
  572. }
  573. }
  574. }
  575. //不存在于ai中
  576. $data = [
  577. 'catid' => 13,
  578. 'title' => $row['title'],
  579. 'content' => '0',
  580. 'topic_1' => '0',
  581. 'topic_2' => '0',
  582. 'topic_3' => '0',
  583. 'didian' => '0',
  584. 'dssj' => '0',
  585. 'fbsj' => '0',
  586. 'tb_time' => $row['create_time'],
  587. 'create_time' => time(),
  588. 'update_time' => time(),
  589. 'status' => 0, //默认手动开启
  590. 'cy' => $cy, //创意
  591. 'zlj' => $zlj, //指令集 json字符串
  592. 'tpzl' => $zlj_end,
  593. 'sjcy' => $json['is_sj'], //随机创意
  594. 'lyjlid' => $row['id'], //来源id
  595. 'sblx' => 3,//设别类型 电脑A
  596. 'is_sc' => 0, //是否生成文章
  597. 'pic_html' => '0',
  598. 'imgs' => '{}'
  599. ];
  600. $run = Db::name('cms_ai')->insert($data);
  601. Db::name('cms_zl')->where('id',$row['id'])->update(['is_cf'=>2]); //已检测 同步
  602. echo $run;
  603. }else{
  604. //更新为重复记录
  605. Db::name('cms_zl')->where('id',$row['id'])->update(['is_cf'=>1]);
  606. echo $row['title']."已存在,更新为重复记录";
  607. }
  608. }
  609. }
  610. /*
  611. * 定时自动通过合法的发文标题
  612. * http://console.zx2049.com/api/ai/dsTitle13
  613. */
  614. public function dsTitle13()
  615. {
  616. $id_list = Db::name('cms_ai')->where([
  617. 'catid'=>13,
  618. 'status' => 0
  619. ])->limit(10)->column('id');
  620. dump($id_list);
  621. Db::name('cms_ai')->where('id','in',$id_list)->update([
  622. 'status' => 1
  623. ]);
  624. }
  625. /*
  626. * 处理百度的的ai图片 变成本地的
  627. * 定时任务处理
  628. * http://console.zx2049.com/api/ai/bdPicHandle
  629. */
  630. public function bdPicHandle(){
  631. //查找是否已处理图片 本地化
  632. $id_list = Db::name('cms_ai')->where([
  633. 'catid'=>13,
  634. 'is_pic' => 0,
  635. 'is_sc' => 1, //已生成文章
  636. ])->find();
  637. if(!empty($id_list['pic_html'])){
  638. //提取图片
  639. //var_dump($id_list['pic_html']);
  640. $str = htmlspecialchars_decode($id_list['pic_html']);
  641. $pattern="/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.png?]))[\'|\"].*?[\/]?>/";
  642. preg_match_all($pattern,$str,$match);
  643. print_r($match[1]);
  644. //下载文件到本地服务器
  645. $imgs = $match[1];
  646. if(!empty($imgs)){
  647. $dir_name = '/ai/images/'.date('Y-m-d',time()).'/';
  648. $dir = '.'.$dir_name;
  649. if(!is_dir($dir)) {
  650. mkdir($dir, 0777, true);
  651. }
  652. $new_img = [];
  653. foreach ($imgs as $k => $v){
  654. //去除字符
  655. $v = str_replace("?", "", $v);
  656. $this->downloadImage($v, $dir);
  657. $filename = pathinfo($v, PATHINFO_BASENAME);
  658. $new_img[] = $dir_name.$filename;
  659. }
  660. //保存图片信息
  661. $new_img = json_encode($new_img);
  662. Db::name('cms_ai')->where([
  663. 'id' => $id_list['id']
  664. ])->update([
  665. 'is_pic' => 1,
  666. 'imgs' => $new_img,
  667. 'username' => 'admin',
  668. 'sysadd' => 1,
  669. 'hits' => 1
  670. ]);
  671. }
  672. }
  673. }
  674. //保存文件方法
  675. public function saveAsImage($url, $file, $path)
  676. {
  677. $filename = pathinfo($url, PATHINFO_BASENAME);
  678. $resource = fopen($path . $filename, 'a');
  679. fwrite($resource, $file);
  680. fclose($resource);
  681. }
  682. //下载文件方法
  683. public function downloadImage($url, $path)
  684. {
  685. $ch = curl_init();
  686. curl_setopt($ch, CURLOPT_URL, $url);
  687. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  688. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
  689. //避免https 的ssl验证
  690. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  691. curl_setopt($ch, CURLOPT_SSLVERSION, false);
  692. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  693. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  694. $file = curl_exec($ch);
  695. if(curl_exec($ch) === false) echo 'Curl error: ' . curl_error($ch);
  696. curl_close($ch);
  697. $this->saveAsImage($url, $file, $path);
  698. }
  699. }