作者 赵彬吉

AI Blog自动发布

  1 +<?php
  2 +
  3 +namespace App\Console\Commands\Ai;
  4 +
  5 +use App\Http\Logic\Aside\Project\ProjectLogic;
  6 +use App\Models\Ai\AiBlog;
  7 +use App\Models\Ai\AiBlogOpenLog;
  8 +use App\Models\Project\AiBlogTask as AiBlogTaskModel;
  9 +use App\Models\Project\Project;
  10 +use App\Models\Project\ProjectKeyword;
  11 +use App\Models\WebSetting\WebSetting;
  12 +use App\Services\AiBlogService;
  13 +use App\Services\ProjectServer;
  14 +use Illuminate\Console\Command;
  15 +use Illuminate\Support\Facades\DB;
  16 +use Illuminate\Support\Facades\Log;
  17 +
  18 +/**
  19 + * 自动发布AI博客任务
  20 + * Class AiBlogAutoPublish
  21 + * @package App\Console\Commands\Ai
  22 + * @author zbj
  23 + * @date 2025/3/6
  24 + */
  25 +class AiBlogAutoPublish extends Command
  26 +{
  27 + /**
  28 + * The name and signature of the console command.
  29 + *
  30 + * @var string
  31 + */
  32 + protected $signature = 'ai_blog_auto_publish {action}';
  33 +
  34 + /**
  35 + * The console command description.
  36 + *
  37 + * @var string
  38 + */
  39 + protected $description = '自动发布AI Blog';
  40 +
  41 +
  42 + /**
  43 + * @return bool
  44 + * @author zbj
  45 + * @date 2025/3/6
  46 + */
  47 + public function handle()
  48 + {
  49 + $action = $this->argument('action');
  50 + if($action == 'auto_publish'){
  51 + $this->auto_publish();
  52 + }
  53 + if($action == 'auto_open'){
  54 + $this->auto_open();
  55 + }
  56 + }
  57 +
  58 + public function auto_publish()
  59 + {
  60 + $this->output('开始自动发布博客文章');
  61 + $projects = Project::where('is_ai_blog', 1)->get();
  62 +
  63 + foreach ($projects as $project) {
  64 + $this->output("项目{$project->id}开始自动发布");
  65 + $next_auto_date = AiBlogTaskModel::where('project_id', $project->id)->whereNotNull('next_auto_date')->orderBy('id', 'desc')->value('next_auto_date');
  66 + if($next_auto_date && $next_auto_date > date('Y-m-d')){
  67 + $this->output("项目{$project->id}未到执行时间" . $next_auto_date);
  68 + continue;
  69 + }
  70 + //核心关键词+网站关键词
  71 + $main_keywords = ProjectKeyword::where('project_id', $project->id)->value('main_keyword');
  72 + $main_keywords = explode("\r\n", $main_keywords);
  73 + ProjectServer::useProject($project->id);
  74 + $site_keywords = WebSetting::where('project_id', $project->id)->value('keyword');
  75 + DB::disconnect('custom_mysql');
  76 + $site_keywords = explode(",", $site_keywords);
  77 + $keywords = array_filter(array_merge($main_keywords, $site_keywords));
  78 + $keywords = array_map('trim', $keywords);
  79 + if (empty($keywords)) {
  80 + $this->output("项目{$project->id}未获取到关键词");
  81 + }
  82 + $last_task = AiBlogTaskModel::where('project_id', $project->id)->orderBy('id', 'desc')->first();
  83 + //如果没有发布过AI blog任务, 第一次提交3个任务
  84 + if (!$last_task) {
  85 + for ($i = 0; $i < 3; $i++) {
  86 + $this->createTask($keywords, $project->id);
  87 + }
  88 + } else {
  89 + $this->createTask($keywords, $project->id);
  90 + }
  91 + }
  92 + }
  93 +
  94 + public function createTask($keywords, $project_id){
  95 + $keyword = $keywords[array_rand($keywords)];
  96 + $aiBlogService = new AiBlogService($project_id);
  97 + $result = $aiBlogService->setRoute($keyword)->createTask($keyword);
  98 + if ($result['status'] == 200) {
  99 + $aiBlogTaskModel = new AiBlogTaskModel();
  100 + $next_auto_date = date('Y-m-d', strtotime('+' . mt_rand(3,6) . 'days')); //每3-6天自动发布
  101 + $aiBlogTaskModel->addReturnId(['project_id' => $project_id, 'type' => 2, 'task_id' => $result['data']['task_id'], 'status' => 1, 'next_auto_date' => $next_auto_date]);
  102 +
  103 + ProjectServer::useProject($project_id);
  104 + $aiBlogModel = new AiBlog();
  105 +
  106 + $start = strtotime('10:00:00');
  107 + $end = strtotime('16:00:00');
  108 + $randomTimestamp = mt_rand($start, $end);
  109 + $created_at = date("Y-m-d H:i:s", $randomTimestamp);
  110 +
  111 + $aiBlogModel->addReturnId(['keyword' => $keyword, 'status' => 1, 'task_id' => $result['data']['task_id'], 'project_id' => $project_id, 'created_at' => $created_at]);
  112 + DB::disconnect('custom_mysql');
  113 + $this->output("任务创建成功");
  114 + } else {
  115 + $this->output('任务创建失败:' . json_encode($result));
  116 + }
  117 + }
  118 +
  119 + /**
  120 + * 上线的推广项目自动开启
  121 + * @author zbj
  122 + * @date 2025/3/7
  123 + */
  124 + public function auto_open()
  125 + {
  126 + $this->output('上线的推广项目自动开启');
  127 + $projects = Project::whereIn('type', [Project::TYPE_TWO, Project::TYPE_FOUR])
  128 + ->whereNotNull('uptime')->where('is_ai_blog', 0)
  129 + ->get();
  130 + foreach ($projects as $project) {
  131 + //未开启过 自动开启
  132 + if (!AiBlogOpenLog::isOpened($project->id)) {
  133 + //开启
  134 + $project->is_ai_blog = 1;
  135 + $project->save();
  136 + //创建AI博客项目
  137 + (new ProjectLogic())->setAiBlog($project->id, $project->main_lang_id, 1, $project->title);
  138 + //开启日志
  139 + AiBlogOpenLog::addLog($project->id);
  140 +
  141 + $this->output('自动开启项目:' . $project->id);
  142 + }
  143 + }
  144 + }
  145 +
  146 + /**
  147 + * 输出message
  148 + * @param $message
  149 + */
  150 + public function output($message)
  151 + {
  152 + Log::channel('ai_blog')->info($message);
  153 + echo date('Y-m-d H:i:s') . ' ' . $message . PHP_EOL;
  154 + }
  155 +}
@@ -42,7 +42,7 @@ class AiBlogTask extends Command @@ -42,7 +42,7 @@ class AiBlogTask extends Command
42 public function handle(){ 42 public function handle(){
43 $aiBlogTaskModel = new AiBlogTaskModel(); 43 $aiBlogTaskModel = new AiBlogTaskModel();
44 while (true){ 44 while (true){
45 - $list = $aiBlogTaskModel->list(['status'=>1,'type'=>2],'id',['*'],'asc',1000); 45 + $list = $aiBlogTaskModel->list(['status'=>1,'type'=>2, 'created_at' => ['<', date('Y-m-d H:i:s')]],'id',['*'],'asc',1000);
46 if(empty($list)){ 46 if(empty($list)){
47 sleep(300); 47 sleep(300);
48 continue; 48 continue;
@@ -41,6 +41,9 @@ class Kernel extends ConsoleKernel @@ -41,6 +41,9 @@ class Kernel extends ConsoleKernel
41 $schedule->command('sync_inquiry_text')->dailyAt('09:00')->withoutOverlapping(1); 41 $schedule->command('sync_inquiry_text')->dailyAt('09:00')->withoutOverlapping(1);
42 //FB询盘费用同步 42 //FB询盘费用同步
43 $schedule->command('sync_ad_cost')->everyThirtyMinutes()->withoutOverlapping(1); 43 $schedule->command('sync_ad_cost')->everyThirtyMinutes()->withoutOverlapping(1);
  44 +
  45 +// $schedule->command('ai_blog_auto_publish auto_open')->everyMinute()->withoutOverlapping(1);
  46 + $schedule->command('ai_blog_auto_publish auto_publish')->dailyAt('07:00')->withoutOverlapping(1);
44 } 47 }
45 48
46 /** 49 /**
  1 +<?php
  2 +
  3 +namespace App\Models\Ai;
  4 +
  5 +use App\Models\Base;
  6 +
  7 +/**
  8 + * AI Blog开启日志
  9 + * Class AiBlogOpenLog
  10 + * @package App\Models\Ai
  11 + * @author zbj
  12 + * @date 2025/3/7
  13 + */
  14 +class AiBlogOpenLog extends Base
  15 +{
  16 + protected $table = 'gl_ai_blog_open_log';
  17 +
  18 +
  19 + public static function addLog($project_id, $manage_id = 0, $status = 1){
  20 + $log = new self();
  21 + $log->project_id = $project_id;
  22 + $log->manage_id = $manage_id;
  23 + $log->status = $status;
  24 + $log->save();
  25 + }
  26 +
  27 + /**
  28 + * 是否有开启记录
  29 + * @author zbj
  30 + * @date 2025/3/7
  31 + */
  32 + public static function isOpened($project_id){
  33 + $model = self::where('project_id', $project_id)->where('status', 1)->first();
  34 + return (bool)$model;
  35 + }
  36 +}
@@ -110,7 +110,7 @@ class Base extends Model @@ -110,7 +110,7 @@ class Base extends Model
110 */ 110 */
111 public function addReturnId($data){ 111 public function addReturnId($data){
112 $data = $this->filterRequestData($data); 112 $data = $this->filterRequestData($data);
113 - $data['created_at'] = date('Y-m-d H:i:s'); 113 + $data['created_at'] = $data['created_at'] ?? date('Y-m-d H:i:s');
114 $data['updated_at'] = $data['created_at']; 114 $data['updated_at'] = $data['created_at'];
115 return $this->insertGetId($data); 115 return $this->insertGetId($data);
116 } 116 }
@@ -9,6 +9,10 @@ @@ -9,6 +9,10 @@
9 9
10 namespace App\Services; 10 namespace App\Services;
11 11
  12 +use App\Helper\Translate;
  13 +use App\Models\Project\ProjectAiSetting;
  14 +use Illuminate\Database\Eloquent\Model;
  15 +
12 class AiBlogService 16 class AiBlogService
13 { 17 {
14 public $url = 'https://ai-extend.ai.cc/'; 18 public $url = 'https://ai-extend.ai.cc/';
@@ -21,6 +25,23 @@ class AiBlogService @@ -21,6 +25,23 @@ class AiBlogService
21 25
22 public $task_id = '';//任务id 26 public $task_id = '';//任务id
23 public $author_id = '';//作者id 27 public $author_id = '';//作者id
  28 +
  29 + public function __construct($project_id = 0)
  30 + {
  31 + if($project_id){
  32 + $projectAiSettingModel = new ProjectAiSetting();
  33 + $aiSettingInfo = $projectAiSettingModel->read(['project_id'=>$project_id]);
  34 + $this->mch_id = $aiSettingInfo['mch_id'];
  35 + $this->key = $aiSettingInfo['key'];
  36 + }
  37 + }
  38 +
  39 + public function setRoute($keyword)
  40 + {
  41 + $this->route = generateRoute(Translate::tran($keyword, 'en'));
  42 + return $this;
  43 + }
  44 +
24 /** 45 /**
25 * @remark :创建项目 46 * @remark :创建项目
26 * @name :createProject 47 * @name :createProject
@@ -191,6 +191,12 @@ return [ @@ -191,6 +191,12 @@ return [
191 'level' => 'debug', 191 'level' => 'debug',
192 'days' => 14, 192 'days' => 14,
193 ], 193 ],
  194 + 'ai_blog' => [
  195 + 'driver' => 'daily',
  196 + 'path' => storage_path('logs/ai_blog/laravel.log'),
  197 + 'level' => 'debug',
  198 + 'days' => 30,
  199 + ],
194 ], 200 ],
195 //操作日志 201 //操作日志
196 'operator_log' =>[ 202 'operator_log' =>[