AiBlogAutoPublish.php 10.7 KB
<?php

namespace App\Console\Commands\Ai;

use App\Http\Logic\Aside\Project\ProjectLogic;
use App\Models\Ai\AiBlog;
use App\Models\Ai\AiBlogKeyword;
use App\Models\Ai\AiBlogOpenLog;
use App\Models\Project\AiBlogTask as AiBlogTaskModel;
use App\Models\Project\Project;
use App\Models\Project\ProjectKeyword;
use App\Models\RankData\RankData;
use App\Models\WebSetting\WebSetting;
use App\Services\AiBlogService;
use App\Services\DingService;
use App\Services\ProjectServer;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

/**
 * 自动发布AI博客任务
 * Class AiBlogAutoPublish
 * @package App\Console\Commands\Ai
 * @author zbj
 * @date 2025/3/6
 */
class AiBlogAutoPublish extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'ai_blog_auto_publish {action}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '自动发布AI Blog';


    /**
     * @return bool
     * @author zbj
     * @date 2025/3/6
     */
    public function handle()
    {
        $action = $this->argument('action');
        if($action == 'auto_publish'){
            $this->auto_publish();
        }
        if($action == 'auto_open'){
            $this->auto_open();
        }
    }

    public function auto_publish()
    {
        $this->output('开始自动发布博客文章');
        $projects = Project::where('is_ai_blog', 1)->whereIn('type',[1,2,3,4,6])->where('delete_status',0)->where('site_status',0)->where('extend_type',0)->get();
        foreach ($projects as $project) {
            try {
                $this->output("项目{$project->id}开始自动发布");
                if(!$project->deploy_optimize['is_ai_blog_send']){
                    $this->output("项目{$project->id}未开启自动发布" . $project->deploy_optimize['start_date']);
                    continue;
                }
                if(($project->deploy_optimize['start_date'] > date('Y-m-d')) || !$project->deploy_optimize['start_date']){
                    $this->output("项目{$project->id}未到推广时间" . $project->deploy_optimize['start_date']);
                    continue;
                }
                $next_auto_date = AiBlogTaskModel::where('project_id', $project->id)->where('type', 2)->whereNotNull('next_auto_date')->orderBy('id', 'desc')->value('next_auto_date');
                if($next_auto_date && $next_auto_date > date('Y-m-d')){
                    $this->output("项目{$project->id}未到执行时间" . $next_auto_date);
                    continue;
                }
                $aiKeywordModel = new AiBlogKeyword();
                $keywords = $aiKeywordModel->getValue(['project_id'=>$project->id],'keywords');
                if(empty($keywords)){
                    //核心关键词+网站关键词+白帽关键词
                    $main_keywords = ProjectKeyword::where('project_id', $project->id)->value('main_keyword');
                    $main_keywords = explode("\r\n", $main_keywords);
                    $seo_keywords = ProjectKeyword::where('project_id', $project->id)->value('seo_keywords');
                    $seo_keywords = explode("\r\n", $seo_keywords);
                    ProjectServer::useProject($project->id);
                    $site_keywords = WebSetting::where('project_id', $project->id)->value('keyword');
                    DB::disconnect('custom_mysql');
                    $site_keywords = explode(",", $site_keywords);
                    $keywords = array_filter(array_merge($main_keywords, $site_keywords, $seo_keywords));
                    $keywords = array_map('trim', $keywords);
                }else{
                    $keywords = explode("\r\n", $keywords);
                    $keywords = array_map('trim', $keywords); // 清理空格
                    $keywords = array_filter($keywords); // 移除空值
                }
                if (empty($keywords)) {
                    $this->output("项目{$project->id}未获取到关键词");
                    continue;
                }
                $last_task = AiBlogTaskModel::where('project_id', $project->id)->where('type', 2)->orderBy('id', 'desc')->first();
                $compliance = RankData::where(['project_id' => $project->id, 'lang' => ''])->value('is_compliance');
                $frequency = Project::typeBlogFrequency($project->deploy_optimize->send_ai_blog_frequency);
                $frequency = explode('-', $frequency);
                //1、之前测试那批项目,按照正常频率发送;
                //2、未达标的项目,开启AIblog, 并立即推送三篇;
                //3、其他项目等下下周 1 (2025-03-17)开始推送第一篇, 之后按照正频率发送;
                if (!$last_task) {
                    if(strpos($frequency[0],'/')){
                        $frequency = [1,1];//默认每天执行
                    }
                    if(!$compliance) {
                        for ($i = 0; $i < 3; $i++) {
                            $this->createTask($keywords, $project->id, $frequency);
                        }
                    }else{
                        if(date('Y-m-d') >= '2025-03-17'){
                            $this->createTask($keywords, $project->id, $frequency);
                        }
                    }
                } else {
                    if(strpos($frequency[0],'/')){//一天2/3篇
                        $aiBlogTaskModel = new AiBlogTaskModel();
                        $frequency = explode('/', $frequency[0]);
                        //查询当前已发布几篇
                        $count = $aiBlogTaskModel->counts(['next_auto_date' => date('Y-m-d', strtotime('+1 day')),'project_id' => $project->id]);
                        while ($count < ($frequency[1] ?? 2) && ($count <= 3)){
                            $this->createTask($keywords, $project->id, [1,1]);
                            $count++;
                        }
                    }else{
                        $this->createTask($keywords, $project->id, $frequency);
                    }
                }
            }catch (\Exception $e){
                (new DingService())->handle([
                    'keyword' => 'AI_BLOG自动发布失败',
                    'msg' => '项目ID:' . $project->id . PHP_EOL .
                             '错误信息:' . $e->getMessage() . PHP_EOL .
                             '错误文件:' . $e->getFile() . PHP_EOL .
                             '错误行数:' . $e->getLine(),
                    'isAtAll' => true, // 是否@所有人
                ]);
                $this->output("自动发布失败:" . $e->getMessage() . $e->getFile() . $e->getLine());
            }
            sleep(5);
        }
    }

    public function createTask($keywords, $project_id, $frequency){
        $keyword = $keywords[array_rand($keywords)];
        $aiBlogService = new AiBlogService($project_id);
        $result = $aiBlogService->createTask($keyword);
        if ($result['status'] == 200) {
            $aiBlogTaskModel = new AiBlogTaskModel();
            $next_auto_date = date('Y-m-d', strtotime('+' . mt_rand($frequency[0] ?? 3, $frequency[1] ?? 6) . 'days')); //每3-6天自动发布
            $aiBlogTaskModel->addReturnId(['project_id' => $project_id, 'type' => 2, 'task_id' => $result['data']['task_id'], 'status' => 1, 'next_auto_date' => $next_auto_date]);
            ProjectServer::useProject($project_id);
            $aiBlogModel = new AiBlog();
            $start = strtotime('10:00:00');
            $end = strtotime('16:00:00');
            $randomTimestamp = mt_rand($start, $end);
            $created_at = date("Y-m-d H:i:s", $randomTimestamp);
            $aiBlogModel->addReturnId(['keyword' => $keyword, 'status' => 1, 'task_id' => $result['data']['task_id'], 'project_id' => $project_id, 'created_at' => $created_at]);
            DB::disconnect('custom_mysql');
            $this->output("任务创建成功");
        } else {
            $this->output('任务创建失败:' . json_encode($result));
        }
    }

    /**
     * 上线的推广项目自动开启
     * @author zbj
     * @date 2025/3/7
     */
    public function auto_open()
    {
        while (true) {
            $this->output('上线的推广项目自动开启');

            $projects = Project::whereIn('type', [Project::TYPE_TWO, Project::TYPE_FOUR])
                ->whereIn('id', function ($query) {
                    //按推广时间
                    $query->select('project_id')
                        ->from('gl_project_deploy_optimize')
                        ->where('start_date', '<=', date('Y-m-d'))
                        ->where('start_date', '<>', '');
                })
                ->where('is_ai_blog', 0)
                ->get();

            foreach ($projects as $project) {
                try {
                    //未开启过 自动开启
                    if (!AiBlogOpenLog::isOpened($project->id)) {
                        //创建AI博客项目
                        $deploy_optimize = $project->deploy_optimize;
                        (new ProjectLogic())->setAiBlog($project->id, $project->main_lang_id, 1, $project->company, $deploy_optimize->company_en_name, $deploy_optimize->company_en_description,$project->is_related_video ?? 0);

                        //开启
                        $project->is_ai_blog = 1;

                        //开启自动发布
                        $project->deploy_optimize->is_ai_blog_send = 1;
                        $project->deploy_optimize->save();

                        $project->save();

                        //开启日志
                        AiBlogOpenLog::addLog($project->id);

                        $this->output('自动开启项目:' . $project->id);
                    }
                }catch (\Exception $e){
                    (new DingService())->handle([
                        'keyword' => 'AI_BLOG自动开启失败',
                        'msg' => '项目ID:' . $project->id . PHP_EOL .
                            '错误信息:' . $e->getMessage() . PHP_EOL .
                            '错误文件:' . $e->getFile() . PHP_EOL .
                            '错误行数:' . $e->getLine(),
                        'isAtAll' => true, // 是否@所有人
                    ]);
                    $this->output("自动开启失败:" . $e->getMessage() . $e->getFile() . $e->getLine());
                }
            }
            sleep(60);
        }
    }

    /**
     * 输出message
     * @param $message
     */
    public function output($message)
    {
        Log::channel('ai_blog')->info($message);
        echo date('Y-m-d H:i:s') . ' ' . $message . PHP_EOL;
    }
}