SyncInquiryRelay.php 11.8 KB
<?php
/**
 * Created by PhpStorm.
 * User: zhl
 * Date: 2025/2/13
 * Time: 16:45
 */

namespace App\Console\Commands\Inquiry;

use App\Helper\Translate;
use App\Helper\Validate;
use App\Models\Inquiry\InquiryInfo;
use App\Models\Project\InquiryFilterConfig;
use App\Models\Project\Project;
use App\Services\InquiryRelayService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Str;

class SyncInquiryRelay extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'sync_inquiry_relay';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '同步询盘信息:站群询盘,';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }


    public function handle()
    {
        $this->output('开始同步表单系统询盘');
        $this->getInquiryForm();

        $this->output('开始同步SC平台询盘');
        $this->getInquirySzcm();

        $this->output('开始同步FS平台询盘');
        $this->getInquiryFs();
    }

    /**
     * 获取表单系统中询盘信息
     * message_sign唯一值:md5(name+email+phone+ip+time)
     */
    public function getInquiryForm()
    {
        $service = new InquiryRelayService();
        $result = $service->getInquiryRelay();
        if (isset($result['status']) && $result['status'] == 200) {
            $data = $result['data'] ?? [];
            foreach ($data as $item) {
                $this->saveDate($item, $item['source_type']);
            }
        }
    }

    /**
     * 获取秋哥asp采集询盘信息
     * type固定4
     * message_sign唯一值:md5(name+email+phone+ip+time)
     * 先查数据库最大origin_key,再获取数据
     */
    public function getInquirySzcm()
    {
        $max_origin_key = InquiryInfo::where('type', InquiryInfo::TYPE_SPIDER)->orderBy('origin_key', 'desc')->value('origin_key');
        if ($max_origin_key) {
            $start_id = $max_origin_key + 1;
        } else {
            $start_id = 65029;
        }

        // TODO 由于该渠道数据不规则, 可能某个ID获取不到数据, 无法判断是因为已经没有数据了, 还是因为解析问题导致, 所以当未获取到数据时, 多向后取几次数据, 连续几次没有数据, 就认为已经获取到最大数据。
        $service = new InquiryRelayService();
        $pre = 0;
        while ($start_id > 0) {
            $result = $service->getInquirySzcm($start_id);
            if (empty($result) && $pre <= 3) {
                $start_id++;
                $pre++;
                continue;
            }

            if ($result) {
                $this->saveDate($result, InquiryInfo::TYPE_SPIDER);
                $start_id++;
                $pre = 0;
            }

            if ($pre > 3)
                break;
        }
        return true;
    }

    /**
     * @return bool
     * @throws \Exception
     * @author Akun
     * @date 2025/03/04 11:48
     */
    public function getInquiryFs()
    {
        $service = new InquiryRelayService();
        $next_page_url = 'https://www.findsupply.com/api/external?page=1&pagesize=50';
        $model = new InquiryInfo();
        while ($next_page_url) {
            $result = $service->getInquiryFs($next_page_url);
            $data = $result['data'];
            $next_page_url = $result['next_page_url'];

            if ($data) {
                foreach ($data as $item) {
                    $message_sign = md5($item['name'] . $item['email'] . $item['phone'] . $item['ip'] . $item['time']);
                    $inquiry_info = $model->where('message_sign', $message_sign)->first();
                    if ($inquiry_info) {
                        $next_page_url = null;
                        break;
                    }
                    $this->saveDate($item, InquiryInfo::TYPE_FIND_SUPPLY);
                }
            }
        }
        return true;
    }

    /**
     * 询盘数据入库
     * @param $data
     * @param $type
     * @return bool
     */
    public function saveDate($data, $type)
    {
        $model = new InquiryInfo();
        $message_sign = md5($data['name'] . $data['email'] . $data['phone'] . $data['ip'] . $data['time']);
        $inquiry_info = $model->where('message_sign', $message_sign)->first();
        if ($inquiry_info)
            return true;

        //没有IP,根据submit_country获取
        if (empty($data['ip']) && isset($data['submit_country']) && $data['submit_country']) {
            $chinese_name = DB::table('gl_world_country_city')->where('pid', 0)->where('iso2', $data['submit_country'])->value('chinese_name');
            $data['ip'] = $this->getIpData($chinese_name);
        }

        //获取country
        $country = '';
        if ($data['ip']) {
            $country = file_get_contents("http://ip.globalso.com?ip=" . $data['ip']);
        }

        //翻译message
        $message_cn = '';
        $re_message_trans = Translate::translate($data['message'], 'zh');
        if (isset($re_message_trans[0]['code']) && $re_message_trans[0]['code'] == 200) {
            $message_cn = $re_message_trans[0]['texts'];
        }

        //获取页面上title和keywords
        $html = curl_c($data['refer'], false);

        if (empty($data['title'])) {
            $data['title'] = '';
            preg_match_all('/<title>([\w\W]*?)<\/title>/', $html, $matches);
            if (!empty($matches[1])) {
                $data['title'] = substr($matches[1][0], 0, 255);
            }
        }

        $keywords = '';
        preg_match_all('/<meta\s+[^>]*?name=[\'|\"]keywords[\'|\"]\s+[^>]*?content=[\'|\"]([\w\W]*?)[\'|\"]/', $html, $matches);
        if (!empty($matches[1])) {
            $keywords = substr($matches[1][0], 0, 255);
        }

        if (empty($data['origin_key'])) {
            $data['origin_key'] = 0;
        }

        if (empty($data['image'])) {
            $data['image'] = '';
        }

        //判断手机和邮箱是否有效
        $email_status = 0;
        if ($data['email']) {
            $check_email = Validate::email($data['email']);
            $email_status = $check_email ? 1 : 0;
        }
        $phone_status = 0;
        if ($data['phone']) {
            $num_phone = preg_replace('/\D/', '', $data['phone']) ?? ''; // \D 匹配所有非数字字符
            $check_phone = Validate::phone($num_phone);
            $phone_status = $check_phone ? 1 : 0;
        }

        //邮箱和内容唯一值
        $unique_sign = md5($data['email'] . $data['message']);

        //过滤数据:邮箱内容唯一性,国家,ip,内容,来源,邮箱,电话,姓名
        $remark = $this->inquiryFilter($unique_sign, $country, $data['ip'], $data['message'], $data['refer'], $data['email'], $data['phone'], $data['name']);
        $status = $remark ? InquiryInfo::STATUS_INVALID : InquiryInfo::STATUS_INIT;

        $model->createInquiry($data['name'], $data['phone'], $data['email'], $data['ip'], $country, $data['message'], $message_cn, $type, $data['time'], $data['refer'], $data['title'], $keywords, $message_sign, $data['origin_key'], $data['image'], $email_status, $phone_status, $unique_sign, $status, $remark);
        return true;
    }

    /**
     * 过滤数据
     * @param $unique_sign
     * @param $country
     * @param $ip
     * @param $message
     * @param $refer
     * @param $email
     * @param $phone
     * @param $name
     * @return string
     * @author Akun
     * @date 2025/03/06 15:09
     */
    public function inquiryFilter($unique_sign, $country, $ip, $message, $refer, $email, $phone, $name)
    {
        //邮箱和内容唯一性
        if (InquiryInfo::where('unique_sign', $unique_sign)->first()) {
            return '邮箱内容重复过滤';
        }

        //国内ip
        if ($country == '中国') {
            return '中国内地过滤';
        }

        //QQ邮箱
        if (substr($email, -6) == 'qq.com') {
            return 'QQ邮箱过滤';
        }

        //86开头的手机号
        $num_phone = preg_replace('/\D/', '', $phone) ?? ''; // \D 匹配所有非数字字符
        if (substr($num_phone, 0, 2) == '86') {
            return '86开头手机号过滤';
        }

        //公共规则
        $config = InquiryFilterConfig::getCacheInfoByProjectId(Project::DEMO_PROJECT_ID);
        //过滤国家
        if (!empty($config['filter_countries']) && in_array($country, $config['filter_countries'])) {
            return '过滤国家:' . $country;
        }
        //过滤ip
        if (!empty($config['black_ips']) && in_array($ip, $config['black_ips'])) {
            return '过滤黑名单IP:' . $ip;
        }
        //过滤内容关键字
        if (!empty($config['filter_contents'])) {
            foreach ($config['filter_contents'] as $filter_content) {
                //中文直接包含
                if (preg_match("/^[\x{4e00}-\x{9fa5}]+$/u", $filter_content)) {
                    if (Str::contains($message, $filter_content)) {
                        return '过滤内容:' . $filter_content;
                    }
                } else {
                    //英文要指定词才过滤
                    if (preg_match("/\b" . preg_quote($filter_content, "/") . "\b/i", $message)) {
                        return '过滤内容:' . $filter_content;
                    }
                }
            }
        }
        //过滤内容是否允许包含链接
        if (isset($config['is_allow_link']) && $config['is_allow_link'] == 0) {
            if (Str::contains(strtolower($message), ['http://', 'https://', 'www.'])) {
                return '内容包含链接过滤';
            }
        }
        //过滤来源
        if (!empty($config['filter_referers'])) {
            //只比较path路径
            $paths = array_map(function ($v) {
                return trim(parse_url(Url::to($v), PHP_URL_PATH), '/');
            }, $config['filter_referers']);

            if (in_array(trim(parse_url($refer, PHP_URL_PATH), '/'), $paths)) {
                return '过滤来源链接:' . $refer;
            }
        }
        //过滤邮箱
        if (!empty($config['filter_emails'])) {
            foreach ($config['filter_emails'] as $filter_email) {
                if (Str::contains(strtolower($email), strtolower($filter_email))) {
                    return '过滤邮箱:' . $filter_email;
                }
            }
        }
        //过滤电话
        if (!empty($config['filter_mobiles'])) {
            foreach ($config['filter_mobiles'] as $filter_mobile) {
                if (Str::contains(strtolower($phone), strtolower($filter_mobile))) {
                    return '过滤电话:' . $filter_mobile;
                }
            }
        }
        //过滤姓名
        if (!empty($config['filter_names'])) {
            foreach ($config['filter_names'] as $filter_name) {
                if (Str::contains(strtolower($name), strtolower($filter_name))) {
                    return '过滤姓名:' . $filter_name;
                }
            }
        }

        return '';
    }

    /**
     * 获取国家随机ip
     * @param $country_name
     * @return mixed|string
     * @author Akun
     * @date 2025/02/14 14:19
     */
    public function getIpData($country_name)
    {
        // 有国家 通过国家查询, 如果没有获取到就随机获取
        $where = [];
        $country_name && $where['ip_area'] = $country_name;
        $ip = DB::table('gl_xunpan_ipdata')->where($where)->inRandomOrder()->value('ip');
        if (empty($ip_data)) {
            $ip = DB::table('gl_xunpan_ipdata')->inRandomOrder()->value('ip');
        }
        return $ip;
    }

    public function output($message)
    {
        echo date('Y-m-d H:i:s') . ' | ' . $message . PHP_EOL;
    }
}