作者 lyh

Merge branch 'dev'

正在显示 38 个修改的文件 包含 4344 行增加245 行删除

要显示太多修改。

为保证性能只显示 38 of 38+ 个文件。

APP_NAME=Laravel
APP_ENV=test
APP_KEY=base64:+ouoKlz2sFDOisnROMRpxT/u9xkZJVrXlzP4cfTqPow=
APP_DEBUG=false
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=globalso
DB_USERNAME=debian-sys-maint
DB_PASSWORD=WtujxV73XIclQet0
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
... ... @@ -3,6 +3,8 @@
/public/storage
/storage
/vendor
/uploads
composer.json
.env
.env.backup
.phpunit.result.cache
... ... @@ -14,4 +16,6 @@ yarn-error.log
/.idea
/.vscode
composer.lock
app/Console/Commands/Test/Demo.php
\ No newline at end of file
app/Console/Commands/Test/Demo.php
/public/upload
/public/runtime
... ...
<?php
namespace App\Console\Commands\AyrShare;
use App\Helper\AyrShare as AyrShareHelper;
use App\Models\AyrShare\AyrShare as AyrShareModel;
use Illuminate\Console\Command;
class ShareConfig extends Command
{
public $error = 0;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'share_config';
/**
* The console command description.
*
* @var string
*/
protected $description = '更新用户Ayr_share配置';
/**
* @name :(定时执行更新用户配置)handle
* @author :lyh
* @method :post
* @time :2023/5/12 14:48
*/
public function handle()
{
$ayrShareModel = new AyrShareModel();
//更新用户配置
$lists = $ayrShareModel->lists($this->map,$this->page,$this->row,'id',['id','profile_key','bind_plat_from']);
foreach ($lists['list'] as $k => $v){
if(empty($v['profile_key'])){
continue;
}
//获取当前用户配置
$ayrShareHelper = new AyrShareHelper();
$share_info = $ayrShareHelper->get_profiles_users($v['profile_key']);
if(!isset($share_info['activeSocialAccounts'])){
$ayrShareModel->edit(['bind_plat_from'=>''],['id'=>$v['id']]);
continue;
}
$str = json_encode($share_info['activeSocialAccounts']);
if($str != $v['bind_plat_from']){
$rs = $ayrShareModel->edit(['bind_plat_from'=>$str],['id'=>$v['id']]);
if($rs === false){
$this->error++;
}
}
}
echo $this->error;
}
}
... ...
<?php
namespace App\Console\Commands\AyrShare;
use App\Helper\AyrShare as AyrShareHelper;
use App\Models\AyrShare\AyrRelease as AyrReleaseModel;
use Carbon\Carbon;
use App\Models\AyrShare\AyrShare as AyrShareModel;
use Illuminate\Console\Command;
class ShareUser extends Command
{
public $error = 0;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'share_user';
/**
* The console command description.
*
* @var string
*/
protected $description = '用户一周内无记录清除Ayr_share';
/**
* @name :(定时执行)handle
* @author :lyh
* @method :post
* @time :2023/5/12 14:48
*/
public function handle()
{
echo $this->user_operator_record();
}
/**
* @name : 检测用户是否无操作记录
* @author :lyh
* @method :post
* @time :2023/5/12 14:55
*/
protected function user_operator_record(){
//获取所有ayr_share用户
$ayr_share_model = new AyrShareModel();
$ayr_release = new AyrReleaseModel();
$ayr_share_list = $ayr_share_model->list(['profile_key'=>['!=','']]);
foreach ($ayr_share_list as $v){
$time = Carbon::now()->modify('-7 days')->toDateString();
//创建时间小于7天前的当前时间
if($v['created_at'] > $time){
continue;
}
//查询当前用户是否有未推送的博文
$release_info = $this->release_info($ayr_release,$v);
//有推文时,直接跳出循环
if($release_info !== false){
continue;
}
//查询7天是否发送博文
$release_info = $this->release_seven_info($ayr_release);
//有发送博文,则跳出循环
if($release_info !== false){
continue;
}
//删除用户第三方配置
if(!empty($v['profile_key'])){
$this->del_profiles($v);
continue;
}
//更新数据库
$this->save_ayr_share($ayr_share_model,$v);
}
return $this->error;
}
/**
* @name :(删除第三方配置)del_profiles
* @author :lyh
* @method :post
* @time :2023/6/14 16:10
*/
public function del_profiles($v){
$ayr_share_helper = new AyrShareHelper();
$data_profiles = [
'title'=>$v['title'],
'profileKey'=>$v['profile_key']
];
$res = $ayr_share_helper->deleted_profiles($data_profiles);
if($res['status'] == 'fail'){
echo '第三方删除失败';
return true;
}
return true;
}
/**
* @name :(更新数据库)save_ayr_share
* @author :lyh
* @method :post
* @time :2023/6/14 16:14
*/
public function save_ayr_share(&$ayr_share_model,$v){
//更新数据库
$data = [
'title'=>'',
'bind_platforms'=>'',
'profile_key'=>'',
'ref_id'=>'',
];
$res = $ayr_share_model->edit($data,['id'=>$v['id']]);
if($res == false){
echo '更新数据库失败';
return true;
}
return true;
}
/**
* @name :(查询是否有定时发送报文)info
* @author :lyh
* @method :post
* @time :2023/6/14 16:17
*/
public function release_info(&$ayr_release,$v){
//查询当前用户是否有未推送的博文
$release_info = $ayr_release->read(['schedule_date'=>['>',date('Y-m-d H:i:s',time())],'share_id'=>$v['id']]);
return $release_info;
}
/**
* @param $ayr_release
* @name :(7天内无发送记录)release_seven_info
* @author :lyh
* @method :post
* @time :2023/6/14 16:28
*/
public function release_seven_info(&$ayr_release){
//查看用户是否在一周内有发送博客
$start_at = Carbon::now()->modify('-7 days')->toDateString();
$end_at = Carbon::now()->toDateString();
$release_info = $ayr_release->read(['created_at'=>['between',[$start_at,$end_at]]]);
return $release_info;
}
}
... ...
<?php
namespace App\Console\Commands\Bside\Statistics;
use App\Models\Bside\Statistics\TrafficStatistics;
use App\Models\CustomerVisit\CustomerVisit;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Throwable;
class Logic
{
/**
* @param int $type 统计类型
* @return array
*/
public function getMonths(int $type = TrafficStatistics::TYPE_SOURCE)
{
$date = getPreviousMonthsDate();
$TrafficStatistics = new TrafficStatistics();
$lists = $TrafficStatistics->getMonthsLists($type, $date);
if (!empty($lists)) {
$dd = [];
$lists->map(function ($item) use (&$dd) {
$dd[] = $item->year . '-' . str_pad($item->month, 2, '0', STR_PAD_LEFT);
});
$date = array_diff($date, $dd);
}
return $date;
}
/**
* @param array $column 统计数据
* @param int $type 统计类型
* @param string|null $date 日期 格式:Y-m
* @param string $message
* @return array
* @throws Throwable
*/
public function save(array $column, int $type = TrafficStatistics::TYPE_SOURCE, string $date = null, $message = '统计当月访问来源数据')
{
DB::beginTransaction();
// 获取当天的IP|PV数量
$customerVisit = new CustomerVisit();
$ip_count = $customerVisit->getMonthIPCount($date);
$pv_count = $customerVisit->getMonthPVCount($date);
$column['pvnum'] = $pv_count;
$column['ipnum'] = $ip_count;
$date = $date ?? date('Y-m');
// 统计数据并插入到数据库
$dd = explode('-', $date);
$year = $dd[0];
$month = $dd[1];
$column['year'] = $year;
$column['month'] = $month;
$trafficStatistics = new TrafficStatistics();
$isRes = $trafficStatistics->getMonth($type, $year, $month);
if ($isRes) {
$trafficStatistics = $isRes;
}
foreach ($column as $key => $value) {
$trafficStatistics->$key = $value;
}
$res = $trafficStatistics->save();
if ($res) {
DB::commit();
$meg = "{$date} - {$message}成功!";
} else {
DB::rollBack();
$meg = "{$date} - {$message}失败!";
}
return ['status' => $res, 'msg' => $meg];
}
}
... ...
<?php
namespace App\Console\Commands\Bside\Statistics;
use App\Models\Bside\Statistics\TrafficTrends;
use App\Models\CustomerVisit\CustomerVisit;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Throwable;
class StatisticsDayTrend extends Command
{
public $error = 0;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'statistics_day_trend';
/**
* The console command description.
*
* @var string
*/
protected $description = '统计当天流量趋势数据';
/**
* @return void
* @throws GuzzleException
* @throws Throwable
*/
public function handle()
{
$date = getPreviousDaysDate();
$trafficTrends = new TrafficTrends();
$lists = $trafficTrends->getDaysLists($date);
if (!empty($lists)) {
$date = array_diff($date, $lists->pluck('day')->all());
}
if (!empty($date)) {
foreach ($date as $value) {
echo $this->statistics_day_trend($value);
}
}
echo $this->statistics_day_trend();
}
/**
* 统计当天流量趋势数据PV|IP数量
* @return int|mixed
* @throws GuzzleException|Throwable
*/
protected function statistics_day_trend($date = null)
{
DB::beginTransaction();
$date = $date ?? date('Y-m-d');
// 获取当天的IP|PV数量
$customerVisit = new CustomerVisit();
$ip_count = $customerVisit->getDayIPCount($date);
$pv_count = $customerVisit->getDayPVCount($date);
// 统计数据并插入到数据库
$trafficTrends = new TrafficTrends();
$isRes = $trafficTrends->getDay($date);
if ($isRes) {
$trafficTrends = $isRes;
}
$trafficTrends->day = $date;
$trafficTrends->pvnum = $pv_count;
$trafficTrends->ipnum = $ip_count;
$res = $trafficTrends->save();
if ($res) {
DB::commit();
$this->info($date . ' - 统计当天流量趋势数据PV|IP数量成功');
} else {
DB::rollBack();
$this->error++;
$this->info($date . ' - 统计当天流量趋势数据PV|IP数量失败');
}
return $this->error;
}
}
... ...
<?php
namespace App\Console\Commands\Bside\Statistics;
use App\Models\Bside\Statistics\TrafficStatistics;
use App\Models\CustomerVisit\CustomerVisit;
use Illuminate\Console\Command;
use Throwable;
class StatisticsDistribution extends Command
{
public $error = 0;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'statistics_distribution';
/**
* The console command description.
*
* @var string
*/
protected $description = '统计当月地域分布数据';
public $logic;
public function __construct()
{
parent::__construct();
$this->logic = new Logic();
}
/**
* 定时执行
* @return void
* @throws Throwable
*/
public function handle()
{
$date = $this->logic->getMonths(TrafficStatistics::TYPE_DISTRIBUTION);
if (!empty($date)) {
foreach ($date as $value) {
echo $this->statistics_distribution($value);
}
}
echo $this->statistics_distribution();
}
/**
* 统计当天流量趋势数据PV|IP数量
* @param string|null $date
* @return int|mixed
* @throws Throwable
*/
protected function statistics_distribution(string $date = null)
{
$customerVisit = new CustomerVisit();
$type = TrafficStatistics::TYPE_DISTRIBUTION;
$top = json_encode($customerVisit->getCountryCount($date) ?? []);
$res = $this->logic->save(compact('top', 'type'), $type, $date, '统计当月地域分布数据');
if (!$res['status']) {
$this->info($res['msg']);
$this->error++;
}
$this->info($res['msg']);
return $this->error;
}
}
... ...
<?php
namespace App\Console\Commands\Bside\Statistics;
use App\Models\Bside\Statistics\TrafficStatistics;
use App\Models\CustomerVisit\CustomerVisit;
use Illuminate\Console\Command;
use Throwable;
class StatisticsPage extends Command
{
public $error = 0;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'statistics_page';
/**
* The console command description.
*
* @var string
*/
protected $description = '统计当月受访页面数据';
public $logic;
public function __construct()
{
parent::__construct();
$this->logic = new Logic();
}
/**
* 定时执行
* @return void
*/
public function handle()
{
$date = $this->logic->getMonths(TrafficStatistics::TYPE_PAGE);
if (!empty($date)) {
foreach ($date as $value) {
echo $this->statistics_page($value);
}
}
echo $this->statistics_page();
}
/**
* 统计当月受访页面数据
* @param null $date
* @return int|mixed
* @throws Throwable
*/
protected function statistics_page($date = null)
{
$customerVisit = new CustomerVisit();
$top = json_encode($customerVisit->getPageCount($date) ?? []);
$type = TrafficStatistics::TYPE_PAGE;
$res = $this->logic->save(compact('top', 'type'), $type, $date, '统计当月受访页面数据');
if (!$res['status']) {
$this->info($res['msg']);
$this->error++;
}
$this->info($res['msg']);
return $this->error;
}
}
... ...
<?php
namespace App\Console\Commands\Bside\Statistics;
use App\Models\Bside\Statistics\TrafficStatistics;
use App\Models\CustomerVisit\CustomerVisit;
use Illuminate\Console\Command;
use Throwable;
class StatisticsSource extends Command
{
public $error = 0;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'statistics_source';
/**
* The console command description.
*
* @var string
*/
protected $description = '统计当月访问来源数据';
public $logic;
public function __construct()
{
parent::__construct();
$this->logic = new Logic();
}
/**
* @return void
* @throws Throwable
*/
public function handle()
{
$date = $this->logic->getMonths();
if (!empty($date)) {
foreach ($date as $value) {
echo $this->statistics_source($value);
}
}
echo $this->statistics_source();
}
/**
* 统计当天流量趋势数据
* @param string|null $date
* @return int|mixed
* @throws Throwable
*/
protected function statistics_source(string $date = null)
{
// 获取当天的IP|PV数量
$customerVisit = new CustomerVisit();
$top = json_encode($customerVisit->getUrlCount($date) ?? []);
$type = TrafficStatistics::TYPE_SOURCE;
$res = $this->logic->save(compact('top', 'type'), $type, $date);
if (!$res['status']) {
$this->info($res['msg']);
$this->error++;
}
$this->info($res['msg']);
return $this->error;
}
}
... ...
<?php
namespace App\Console\Commands\Bside\Statistics;
use App\Models\Bside\Statistics\TrafficStatistics;
use App\Models\CustomerVisit\CustomerVisit;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Console\Command;
use Throwable;
class StatisticsTerminal extends Command
{
public $error = 0;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'statistics_terminal';
/**
* The console command description.
*
* @var string
*/
protected $description = '统计当月访问终端数据';
public $logic;
public function __construct()
{
parent::__construct();
$this->logic = new Logic();
}
/**
* @return void
* @throws Throwable
*/
public function handle()
{
$date = $this->logic->getMonths(TrafficStatistics::TYPE_TERMINAL);
if (!empty($date)) {
foreach ($date as $value) {
echo $this->statistics_terminal($value);
}
}
echo $this->statistics_terminal();
}
/**
* 统计当月访问终端数据
* @param string|null $date
* @return int|mixed
* @throws Throwable
*/
protected function statistics_terminal(string $date = null)
{
$customerVisit = new CustomerVisit();
$pcnum = $customerVisit->getTerminalPcCount($date);
$mbnum = $customerVisit->getTerminalMobileCount($date);
$top = json_encode($customerVisit->getCountryCount($date) ?? []);
$type = TrafficStatistics::TYPE_TERMINAL;
$res = $this->logic->save(compact('top', 'type', 'pcnum', 'mbnum'), $type, $date, '统计当月访问终端数据');
if (!$res['status']) {
$this->info($res['msg']);
$this->error++;
}
$this->info($res['msg']);
return $this->error;
}
}
... ...
<?php
namespace App\Console\Commands\Bside\Statistics;
use App\Models\Bside\Statistics\TrafficStatistics;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Console\Command;
use Throwable;
class StatisticsTrend extends Command
{
public $error = 0;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'statistics_trend';
/**
* The console command description.
*
* @var string
*/
protected $description = '统计当月流量趋势数据';
public $logic;
public function __construct()
{
parent::__construct();
$this->logic = new Logic();
}
/**
* 定时执行
* @return void
* @throws GuzzleException|Throwable
*/
public function handle()
{
$date = $this->logic->getMonths(TrafficStatistics::TYPE_TREND);
if (!empty($date)) {
foreach ($date as $value) {
echo $this->statistics_trend($value);
}
}
echo $this->statistics_trend();
}
/**
* 统计当天流量趋势数据
* @param string|null $date
* @return int|mixed
* @throws GuzzleException|Throwable
*/
protected function statistics_trend(string $date = null)
{
$domain = request()->getHttpHost(); //'www.wowstainless.com';
$sta_date = !is_null($date) ? $date . "-01" : date('Y-m-01');
$inquiry = getInquiryInformation($domain, $sta_date);
$innum = $inquiry['count'] ?? 0;
$top = json_encode($inquiry['lists'] ?? []);
$type = TrafficStatistics::TYPE_TREND;
$res = $this->logic->save(compact('top', 'type', 'innum'), $type, $date, '统计当月流量趋势数据');
if (!$res['status']) {
$this->info($res['msg']);
$this->error++;
}
$this->info($res['msg']);
return $this->error;
}
}
... ...
<?php
namespace App\Console\Commands;
use App\Models\Devops\DevopsTaskLog;
use App\Models\Project\Project;
use Illuminate\Console\Command;
use App\Models\Devops\DevopsTask as DevopsTaskModel;
/**
* Class DevopsTask
* @package App\Console\Commands
* @author zbj
* @date 2023/4/25
*/
class DevopsTask extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'devops_task';
/**
* The console command description.
*
* @var string
*/
protected $description = '运维任务执行';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* @return bool
*/
public function handle()
{
while (true){
$tasks = DevopsTaskModel::where('status', DevopsTaskModel::STATUS_PENDING)->get();
foreach ($tasks as $task){
echo "Start task " . $task->id . PHP_EOL;
if($task->type == DevopsTaskModel::TYPE_MYSQL){
$this->updateTable($task);
}
echo "End task " . $task->id . PHP_EOL;
}
sleep(10);
}
}
public function updateTable($task){
$projects = Project::all();
foreach ($projects as $project){
echo "project " . $project->id;
$log = DevopsTaskLog::addLog($task->id, $project->id);
if($log->status == DevopsTaskModel::STATUS_ACTIVE){
continue;
}
if(!$project->mysqlConfig){
$log->status = DevopsTaskLog::STATUS_ERROR;
$log->remark = '未配置数据库';
$log->save();
continue;
}
//DB类是单例模式,生命周期内修改配置不会生效
$conn = new \mysqli(
$project->mysqlConfig->host,
$project->mysqlConfig->user,
$project->mysqlConfig->password,
$project->databaseName(),
$project->mysqlConfig->port,
);
$res = $conn->query($task->sql);
$log->status = $res ? DevopsTaskLog::STATUS_ACTIVE : DevopsTaskLog::STATUS_ERROR;
$log->remark = $res ? '成功' : 'sql执行失败';
$log->save();
echo '-->' . $log->remark . PHP_EOL;
}
$task->status = DevopsTaskModel::STATUS_ACTIVE;
$task->save();
}
}
... ...
<?php
namespace App\Console\Commands\Domain;
use App\Exceptions\AsideGlobalException;
use App\Exceptions\BsideGlobalException;
use App\Http\Logic\Aside\Domain\DomainInfoLogic;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Console\Command;
class DomainTime extends Command
{
public $error = 0;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'domain_time';
/**
* The console command description.
*
* @var string
*/
protected $description = '域名定时任务 更新域名|证书到期时间';
/**
* @name :(定时执行)handle
* @author :lyh
* @method :post
* @time :2023/5/12 14:48
*/
public function handle()
{
echo $this->update_domain_time();
}
/**
* 更新域名|证书到期时间
* @return int|mixed|void
* @throws AsideGlobalException
* @throws BsideGlobalException|GuzzleException
*/
protected function update_domain_time()
{
$domainCon = new DomainInfoLogic();
$all = $domainCon->getAllDomain();
$all = $all->toArray();
if ( empty( $all ) ) {
$this->info( '未获取到数据' );
return;
}
foreach ( $all as $item ) {
$domain = $item['domain'];
// 域名到期时间
$domainT = $domainCon->getDomainTime( $domain );
if ( $domainT ) {
$domain_time = $item['domain_end_time'];
$domainValidFrom = $domainT['validFrom'];
$domainValidTo = $domainT['validTo'];
if ( strtotime( $domain_time ) < strtotime( $domainValidTo ) ) {
$this->info( $domain . '域名到期时间更新成功' );
$domainCon->updateDomain( $item['id'], [ 'domain_end_time' => $domainValidTo ] );
}
} else {
$this->error++;
$this->info( $domain . '域名到期时间获取失败' );
}
// 证书到期时间
$certificateT = $domainCon->getDomainCertificateTime( $domain );
if ( $certificateT ) {
$certificate_time = $item['certificate_end_time'];
$certificateValidFrom = $certificateT['validFrom'];
$certificateValidTo = $certificateT['validTo'];
if ( strtotime( $certificate_time ) < strtotime( $certificateValidTo ) ) {
$this->info( $domain . '证书到期时间更新成功' );
$domainCon->updateDomain( $item['id'], [ 'certificate_end_time' => $certificateValidTo ] );
}
} else {
$this->error++;
$this->info( $domain . '证书到期时间获取失败' );
}
}
return $this->error;
}
}
... ...
<?php
/**
* Created by PhpStorm.
* User: zhl
* Date: 2023/4/12
* Time: 15:33
*/
namespace App\Console\Commands;
use App\Models\Project;
use App\Services\ProjectServer;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
/**
* Class ProjectInitDatabase
* @package App\Console\Commands
*/
class ProjectInit extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'project:init';
/**
* The console command description.
*
* @var string
*/
protected $description = '项目数据库初始化';
protected $connect = null;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* @return bool
*/
public function handle()
{
#TODO 通过项目ID获取项目部署数据库配置, 创建数据库, 同步数据表
$project_id = 102;
$project = Project::getProjectById($project_id);
if (empty($project) || empty($project->mysqlConfig()))
return true;
$this->initDatabase($project);
return true;
}
/**
* @param Project $project
* @return bool
*/
public function initDatabase($project)
{
$create_flag = $this->createDatabase($project);
if (!$create_flag) {
// 创建数据库失败 添加通知以及再次处理
}
// 设置 database.connections.custom_mysql 数据
ProjectServer::useProject($project->id);
// TODO 创建对应库 初始化数据表
$this->initTable();
return true;
}
/**
* @return bool
*/
public function initTable()
{
$database_name = DB::connection('custom_tmp_mysql')->getDatabaseName();
$table = Schema::connection('custom_tmp_mysql')->getAllTables();
$table = array_column($table, 'Tables_in_' . $database_name);
foreach ($table as $v) {
$has_table = Schema::connection('custom_mysql')->hasTable($v);
if ($has_table)
continue;
$connection = DB::connection('custom_tmp_mysql');
$sql = $connection->getDoctrineSchemaManager()
->getDatabasePlatform()
->getCreateTableSQL($connection->getDoctrineSchemaManager()->listTableDetails($v));
DB::connection('custom_mysql')->select($sql[0]);
}
return true;
}
/**
* 创建数据库
* 链接mysql 查询数据库是否存在 创建数据库
* @param Project $project
* @return bool|\mysqli_result|null
*/
public function createDatabase($project)
{
# 该方法需要:composer require parity-bit/laravel-db-commands
// $result = Artisan::call('db:create', [
// '--database' => $database_name,
// ]);
//
// return $result;
if ($this->connect)
return $this->connect;
//连接到 MySQL 服务器
$servername = $project->mysqlConfig()->host;
$username = $project->mysqlConfig()->user;
$password = $project->mysqlConfig()->password;
$conn = new \mysqli($servername, $username, $password);
//检查连接是否成功
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
$this->connect = $conn;
// $result = $conn->query('SHOW DATABASES LIKE \'' . $database_name . '\';');
// if ($result)
// return true;
$result = $conn->query('CREATE DATABASE ' . $project->databaseName() . ';');
return $result;
}
}
<?php
namespace App\Console\Commands\RankData;
use Illuminate\Console\Command;
/**
* Class BaseCommands
* @package App\Console\Commands\RankData
* @author zbj
* @date 2023/5/11
*/
abstract class BaseCommands extends Command
{
/**
* @author zbj
* @date 2023/5/11
*/
public function handle()
{
$try = 3;
do{
$try--;
if($try == 0){
break;
}
$error = 0;
try {
if(!$this->do()){
$error = 1;
}
}catch (\Exception $e){
errorLog($this->signature . ' error', [], $e);
$error = 1;
}
if($error){
echo 'error';
}
$error && sleep(60);
}while($error);
}
abstract function do();
}
... ...
<?php
namespace App\Console\Commands\RankData;
use App\Helper\Arr;
use App\Helper\SemrushApi;
use App\Models\RankData\ExternalLinks as ExternalLinksModel;
use App\Models\Project\DeployOptimize;
/**
* Class ExternalLinks
* @package App\Console\Commands
* @author zbj
* @date 2023/5/9
*/
class ExternalLinks extends BaseCommands
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'rank_data_external_links';
/**
* The console command description.
*
* @var string
*/
protected $description = '排名数据-外链数据';
/**
* @author zbj
* @date 2023/5/6
*/
public function do()
{
$error = 0;
$semrushApi = new SemrushApi();
//有排名api编号的项目
$list = DeployOptimize::where('api_no', '>', 0)->pluck('domain', 'project_id')->toArray();
foreach ($list as $project_id => $domain) {
if(!$domain){
continue;
}
$model = ExternalLinksModel::where('project_id', $project_id)->first();
if ($model && $model->updated_date == getThisWeekStarDate()) {
continue;
}
if (!$model) {
$model = new ExternalLinksModel();
}
//外链数据
$res = $semrushApi->backlinks_overview($domain);
if (!$res) {
$error++;
continue;
}
$data = $this->_data($project_id, $res['total']);
$model->project_id = $project_id;
$model->total = $data['total'];
$model->data = $data['data'];
$model->updated_date = date('Y-m-d');
$model->save();
}
return !$error;
}
/**
* 构造chat数据
* @param $project_id
* @param $total
* @return array|mixed
* @author zbj
* @date 2023/5/10
*/
public function _data($project_id, $total)
{
// //外链数
$data['total'] = intval($total);
$model = ExternalLinksModel::where('project_id', $project_id)->first();
if ($model) {
//特殊处理的外链数
// $data['total'] = ($total > $model->total) ? intval($total) : $model->total; //特殊处理的
//chat数据
$chat_data = Arr::s2a($model['data']);
if (empty($chat_data[date('Y-m-d')])) {
array_shift($chat_data);
}
} else {
//chat数据
for ($i = 1; $i < 12; $i++) {
$date = date("Y-m-d", strtotime(-7 * $i . 'days'));
$chat_data[$date] = ceil($total - ($total * rand(5, 10) / 100));
}
}
$chat_data[date('Y-m-d')] = $data['total'];
$data['data'] = $chat_data;
return $data;
}
}
... ...
<?php
namespace App\Console\Commands\RankData;
use App\Helper\QuanqiusouApi;
use App\Models\Project\DeployOptimize;
use App\Models\RankData\IndexedPages as IndexedPagesModel;
/**
* Class IndexedPages
* @package App\Console\Commands
* @author zbj
* @date 2023/5/11
*/
class IndexedPages extends BaseCommands
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'rank_data_indexed_pages';
/**
* The console command description.
*
* @var string
*/
protected $description = '排名数据-页面收录数';
/**
* @throws \Exception
* @author zbj
* @date 2023/5/11
*/
public function do(){
$error = 0;
$api = new QuanqiusouApi();
//有排名api编号的项目
$list = DeployOptimize::where('api_no', '>', 0)->pluck('api_no', 'project_id')->toArray();
foreach ($list as $project_id => $api_no) {
$model = IndexedPagesModel::where('project_id', $project_id)->first();
if($model && $model->updated_date == getThisWeekStarDate()){
continue;
}
if(!$model){
$model = new IndexedPagesModel();
}
$res = $api->getSiteResPer($api_no);
if(!$res){
$error++;
continue;
}
$model->project_id = $project_id;
$model->data = $res['data'];
$model->updated_date = date('Y-m-d');
$model->save();
}
return !$error;
}
}
... ...
<?php
namespace App\Console\Commands\RankData;
use App\Helper\Arr;
use App\Helper\QuanqiusouApi;
use App\Models\Project\DeployBuild;
use App\Models\Project\DeployOptimize;
use App\Models\RankData\RankData as GoogleRankModel;
/**
* Class GoogleRank
* @package App\Console\Commands
* @author zbj
* @date 2023/5/6
*/
class RankData extends BaseCommands
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'rank_data';
/**
* The console command description.
*
* @var string
*/
protected $description = '谷歌排名数据';
/**
* @author zbj
* @date 2023/5/6
*/
public function do()
{
$error = 0;
$api = new QuanqiusouApi();
//有排名api编号的项目
$list = DeployOptimize::where('api_no', '>' , 0)->select('api_no','minor_languages','project_id')->get();
//当日所有站点谷歌收录数据
$site_res = $api->getSiteRes();
if(!$site_res){
return false;
}
foreach ($list as $item){
$model = GoogleRankModel::where('project_id', $item['project_id'])->where('lang', '')->first();
if (!$model || $model->updated_date != date('Y-m-d')) {
$res = $api->getGoogleRank($item['api_no']);
if(!$res){
$error++;
continue;
}
//收录数
$indexed_pages_num = $site_res[$item['api_no']] ?? 0;
$this->save_rank($item['project_id'], $res, $indexed_pages_num);
}
//有小语种的
$lang_list = $api->getLangList();
if(!empty($lang_list[$item['api_no']])){
$model = GoogleRankModel::where('project_id', $item['project_id'])->where('lang', '<>', '')->first();
if (!$model || $model->updated_date != date('Y-m-d')) {
$res = $api->getGoogleRank($item['api_no'], 1);
if(!$res){
$error++;
continue;
}
$data = [];
//不同的小语种取出来
foreach ($res as $keyword => $v){
$data[Arr::last($v)['lang']][$keyword] = $v;
}
foreach ($data as $lang => $rank){
$this->save_rank($item['project_id'], $rank, 0, $lang);
}
}
}
}
return !$error;
}
/**
* @param $project_id
* @param int $indexed_pages_num
* @param $data
* @param string $lang
* @author zbj
* @date 2023/5/8
*/
public function save_rank($project_id, $data, int $indexed_pages_num = 0, string $lang = ''){
$without_project_ids = []; //不用处理排名的项目
$first_num = $first_page_num = $first_three_pages_num = $first_five_pages_num = $first_ten_pages_num = 0;
if(!$lang){
foreach ($data as &$ranks){
ksort($ranks);
foreach ($ranks as &$rank){
//处理排名
if(!in_array($project_id, $without_project_ids)){
if($rank['position'] >= 10){
$rank['position'] -= 5;
}
//todo 需要特殊处理排名的项目
}
}
$last = Arr::last($ranks);
//第一名
if($last['position'] == 1){
$first_num ++;
}
//排名第一页
if($last['position'] > 0 && $last['position'] <= 10){
$first_page_num ++;
}
//排名前三页
if($last['position'] > 0 && $last['position'] <= 30){
$first_three_pages_num ++;
}
//排名前五页
if($last['position'] > 0 && $last['position'] <= 50){
$first_five_pages_num ++;
}
//排名前十页
if($last['position'] > 0 && $last['position'] <= 100){
$first_ten_pages_num ++;
}
}
}
$where = [
'project_id' => $project_id,
'lang' => $lang
];
$model = GoogleRankModel::where($where)->first();
if(!$model){
$model = new GoogleRankModel();
}
//关键词达标天数
if($model->updated_date != date('Y-m-d')){
//保证关键词数
$keyword_num = DeployBuild::where('project_id', $project_id)->value('keyword_num');
if($first_page_num >= $keyword_num){
$model->compliance_day = $model->compliance_day + 1;
}
}
$model->project_id = $project_id;
$model->first_num = $first_num;
$model->first_page_num = $first_page_num;
$model->first_three_pages_num = $first_three_pages_num;
$model->first_five_pages_num = $first_five_pages_num;
$model->first_ten_pages_num = $first_ten_pages_num;
$model->indexed_pages_num = $indexed_pages_num;
$model->lang = $lang;
$model->data = $data;
$model->updated_date = date('Y-m-d');
$model->save();
}
}
... ...
<?php
namespace App\Console\Commands\RankData;
use App\Helper\Arr;
use App\Helper\QuanqiusouApi;
use App\Models\Project\DeployOptimize;
use App\Models\RankData\RankWeek as RankWeekModel;
/**
* Class WeekRank
* @package App\Console\Commands
* @author zbj
* @date 2023/5/11
*/
class RankWeek extends BaseCommands
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'rank_data_week';
/**
* The console command description.
*
* @var string
*/
protected $description = '排名数据-每周排名数据';
/**
* @author zbj
* @date 2023/5/6
*/
public function do()
{
$error = 0;
//获取每周排名数据
$api = new QuanqiusouApi();
$res = $api->getGoogleRankWeek();
if (!$res) {
return false;
}
$res = Arr::s2a($res);
//有排名api编号的项目
$list = DeployOptimize::where('api_no', '>', 0)->pluck('api_no', 'project_id')->toArray();
foreach ($list as $project_id => $api_no) {
$rank_week = RankWeekModel::where('project_id', $project_id)->first();
if ($rank_week && $rank_week->updated_date == getThisWeekStarDate()) {
//本周数据已更新
continue;
}
if (!$rank_week) {
$rank_week = new RankWeekModel();
}
$rank_week->project_id = $project_id;
$rank_week->data = $res['data'][$api_no];
$rank_week->date = $res['date'];
$rank_week->updated_date = date('Y-m-d');
$rank_week->save();
}
return !$error;
}
}
... ...
<?php
namespace App\Console\Commands\RankData;
use App\Helper\SemrushApi;
use App\Models\RankData\RecommDomain as RecommDomainModel;
use App\Models\Project\DeployOptimize;
/**
* Class RecommDomain
* @package App\Console\Commands
* @author zbj
* @date 2023/5/9
*/
class RecommDomain extends BaseCommands
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'rank_data_recomm_domain';
/**
* The console command description.
*
* @var string
*/
protected $description = '排名数据-外链引荐域名数据';
/**
* @author zbj
* @date 2023/5/6
*/
public function do()
{
$error = 0;
$semrushApi = new SemrushApi();
//有排名api编号的项目
$list = DeployOptimize::where('api_no', '>', 0)->pluck('domain', 'project_id')->toArray();
foreach ($list as $project_id => $domain) {
if(!$domain){
continue;
}
$model = RecommDomainModel::where('project_id', $project_id)->first();
if ($model && $model->updated_date == getThisWeekStarDate()) {
continue;
}
if (!$model) {
$model = new RecommDomainModel();
}
//外链引荐域名
$data = $semrushApi->backlinks_refdomains($domain);
if (!$data) {
$error++;
continue;
}
$model->project_id = $project_id;
$model->data = $data;
$model->updated_date = date('Y-m-d');
$model->save();
}
return !$error;
}
}
... ...
<?php
namespace App\Console\Commands\RankData;
use App\Helper\Arr;
use App\Helper\GoogleSpeedApi;
use App\Models\Project\DeployOptimize;
use App\Models\RankData\Speed as GoogleSpeedModel;
/**
* Class GoogleSpeed
* @package App\Console\Commands
* @author zbj
* @date 2023/5/10
*/
class Speed extends BaseCommands
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'rank_data_speed';
/**
* The console command description.
*
* @var string
*/
protected $description = '排名数据-测速数据';
/**
* @author zbj
* @date 2023/5/10
*/
public function do()
{
$error = 0;
$googleSpeedApi = new GoogleSpeedApi();
//有排名api编号的项目
$list = DeployOptimize::where('api_no', '>', 0)->pluck('domain', 'project_id')->toArray();
foreach ($list as $project_id => $domain) {
$model = GoogleSpeedModel::where('project_id', $project_id)->first();
if ($model && $model->updated_date == getThisWeekStarDate()) {
//今周已更新 跳过
continue;
}
$res = $googleSpeedApi->run($domain);
if (!$res) {
$error++;
}
if (!$model) {
$model = new GoogleSpeedModel;
}
$model->project_id = $project_id;
$model->data = $res;
$model->updated_date = date('Y-m-d');
$model->save();
}
return !$error;
}
}
... ...
... ... @@ -7,6 +7,8 @@
*/
namespace App\Console\Commands\Test;
use App\Models\Devops\ServerConfig;
use App\Services\ProjectServer;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
... ... @@ -42,10 +44,11 @@ class Demo extends Command
*/
public function handle()
{
$sql = 'CREATE DATABASE database_name;';
$results = DB::select($sql);
dd($results);
return true;
preg_match_all("/\@include\(\"([a-z0-9_]+)\"\)/i",'
@include("asdf")@include("")@include("asdtrw2erf")
',$include);
print_r($include);
}
public function printMessage()
... ... @@ -86,4 +89,4 @@ class Demo extends Command
}
dd(1);
}
}
\ No newline at end of file
}
... ...
<?php
namespace App\Console\Commands\Test;
use App\Helper\Arr;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class DiffDb extends Command
{
protected $signature = 'project:diff_db';
/**
* The console command description.
*
* @var string
*/
protected $description = '对比数据库结构';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
public function handle()
{
$custom_mysql_config = [
'database.connections.custom_mysql.host' => '127.0.0.1',
'database.connections.custom_mysql.port' => '3306',
'database.connections.custom_mysql.database' => 'globalso_project_1',
'database.connections.custom_mysql.username' => 'root',
'database.connections.custom_mysql.password' => 'root',
];
config($custom_mysql_config);
$this->output->writeln("开始进行数据表对比!");
$tablesSource = DB::select("show tables");
$tablesRemote = DB::connection('custom_mysql')->select("show tables");
$tablesSource = array_map(function($item){
return Arr::first($item);
}, $tablesSource);
$tablesRemote = array_map(function($item){
return Arr::first($item);
}, $tablesRemote);
$tablesNotInRemote = [];
$tablesInRemote = [];
foreach ($tablesSource as $t) {
if (!in_array($t, $tablesRemote)) {
$tablesNotInRemote[] = $t;
} else {
$tablesInRemote[] = $t;
}
}
//print reports
echo "本地存在,但是不在custom_mysql中的表:" . PHP_EOL;
echo ">>>>>>==================================<<<<<<" . PHP_EOL;
foreach ($tablesNotInRemote as $t) {
echo $t . PHP_EOL;
}
echo ">>>>>>==================================<<<<<<" . PHP_EOL . PHP_EOL . PHP_EOL;
echo "本地与custom_mysql结构不一致的表:" . PHP_EOL;
echo ">>>>>>==================================<<<<<<" . PHP_EOL;
$only127 = $onlyRemote = $modify127 = [];
foreach ($tablesInRemote as $t) {
$columns127 = DB::select("show columns from `{$t}`");
foreach ($columns127 as &$item){
$item = get_object_vars($item);
}
$columnsRemote = DB::connection('custom_mysql')->select("show columns from `{$t}`");
foreach ($columnsRemote as &$item){
$item = get_object_vars($item);
}
$fields127 = $fieldsRemote = [];
foreach ($columns127 as $v) {
$fields127[$v['Field']] = $v;
}
foreach ($columnsRemote as $v) {
$fieldsRemote[$v['Field']] = $v;
}
foreach ($fields127 as $f => $column) {
if (!isset($fieldsRemote[$f])) {
$only127[$t][] = $f;
} else if ($column !== $fieldsRemote[$f]) {
dump($column);
dump($fieldsRemote[$f]);
$modify127[$t][] = $f;
}
}
foreach ($fieldsRemote as $f => $column) {
if (!isset($fields127[$f])) {
$onlyRemote[$t][] = $f;
}
}
}
if (!empty($only127)) {
echo "只本地存在:" . PHP_EOL;
foreach ($only127 as $t => $columns) {
echo $t . ":";
foreach ($columns as $field) {
echo $field . "\t";
}
echo PHP_EOL;
}
}
if (!empty($onlyRemote)) {
echo "只custom_mysql存在:" . PHP_EOL;
foreach ($onlyRemote as $t => $columns) {
echo $t . ":";
foreach ($columns as $field) {
echo $field . "\t";
}
echo PHP_EOL;
}
}
if (!empty($modify127)) {
echo "本地更新:" . PHP_EOL;
foreach ($modify127 as $t => $columns) {
echo $t . ":";
foreach ($columns as $field) {
echo $field . "\t";
}
echo PHP_EOL;
}
}
echo ">>>>>>==================================<<<<<<" . PHP_EOL . PHP_EOL . PHP_EOL;
}
}
... ...
<?php
namespace App\Console\Commands;
use App\Helper\Arr;
use App\Models\Product\Category;
use App\Models\Product\Product;
use App\Models\RouteMap;
use GuzzleHttp\Client;
use GuzzleHttp\Promise\Utils;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
/**
* 网站引流
* Class Traffic
* @package App\Console\Commands
* @author zbj
* @date 2023/5/18
*/
class WebTraffic extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'web_traffic {type}';
/**
* The console command description.
*
* @var string
*/
protected $description = '网站引流';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* google域名后缀
* @var string[]
*/
protected $suffix = [
'co.jp' => '日本',
'com.tr' => '土耳其',
'nl' => '荷兰',
'ru' => '俄罗斯',
'fr' => '法国',
'co.kr' => '韩国',
'fi' => '芬兰',
'be' => '比利时',
'lt' => '立陶宛',
'es' => '西班牙',
'it' => '意大利',
'com.au' => '澳大利亚',
'no' => '挪威',
'al' => '阿尔巴尼亚',
'pt' => '葡萄牙',
'lv' => '拉脱维亚',
'hu' => '匈牙利',
'cz' => '捷克',
'de' => '德国',
'ca' => '加拿大',
'co.in' => '印度',
'co.uk' => '英国',
'com.vn' => '越南',
'com.br' => '巴西',
'co.il' => '以色列',
'pl' => '波兰',
'com.eg' => '埃及',
'co.th' => '泰国',
'sk' => '斯洛伐克',
'ro' => '罗马尼亚',
'com.mx' => '墨西哥',
'com.my' => '马来西亚',
'com.pk' => '巴基斯坦',
'co.nz' => '新西兰',
'co.za' => '南非',
'com.ar' => '阿根廷',
'com.kw' => '科威特',
'com.sg' => '新加坡',
'com.co' => '哥伦比亚',
'co.id' => '印度尼西亚',
'gr' => '希腊',
'bg' => '保加利亚',
'mn' => '蒙古',
'dk' => '丹麦',
'com.sa' => '沙特阿拉伯',
'com.pe' => '秘鲁',
'com.ph' => '菲律宾',
'com.ua' => '乌克兰',
'ge' => '格鲁吉亚',
'ae' => '阿拉伯联合酋长国',
'tn' => '突尼斯',
];
/**
* 概率值
* @var int[]
*/
protected $sjjg = [720, 280];//访问间隔占比 访问|不访问
//访问页面类型占比 产品详情页、单页|产品分类页
protected $ymzb = [
'urls_cats' => 700,
'urls_details' => 300
];
protected $sdzb = [600, 200, 150, 50]; //访问页面深度占比 1页|2页|3-6页|7-11页
protected $yddzb = [1 => 700, 2 => 300]; //移动端占比 pc|mobile
//模拟访问来源占比 (美国)
protected $lyzb = [
'https://www.google.com/' => 630,
'http://www.google.com/' => 30,
'http://www.bing.com/' => 20,
'https://www.bing.com/' => 5,
'https://www.youtube.com/' => 5,
'https://search.yahoo.com/' => 5,
'https://www.facebook.com/' => 5,
];
protected $otherzb = [700, 300]; //模拟访问来源占比 (非美国) google.com|google.其他后缀
protected $pc_ua = [
0 => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
1 => 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36',
2 => 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1'
];
protected $mobile_ua = [
0 => 'Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko; googleweblight) Chrome/38.0.1025.166 Mobile Safari/535.19',
];
/**
* @return bool
*/
public function handle()
{
$type = $this->argument('type');
$this->sleep($type);
$project_list = $this->getProjectList($type);
$project_chunk = array_chunk($project_list,500,true);
foreach ($project_chunk as $chunk) {
$need_project = [];
foreach ($chunk as $project) {
//随机引流间隔
$res_sjjg = $this->get_rand($this->sjjg);
if ($res_sjjg == 1) {
continue;
}
$project_urls = $this->getProductUrls($project['project_id']);
$project_urls['home'] = $project['domain'];
//随机访问页面
$project['visit_urls'] = $this->getVisitUrls($project_urls);
//随机客户端
$project['device_port'] = $this->get_rand($this->yddzb);
$project['user_agent'] = $project['device_port'] == 1 ? Arr::random($this->pc_ua) : Arr::random($this->mobile_ua);
$need_project[] = $project;
}
//随机访问ip
$ips = $this->getIpAreas(count($need_project));
//最多10层深度
$client = new Client(['verify' => false]);
for ($j = 0; $j < 10; $j++) {
for ($j = 0; $j < 10; $j++) {
//并发请求
$promises = [];
foreach ($need_project as $project_key => $project) {
if (empty($project['visit_urls'][$j])) {
continue;
}
$data = [
'ip' => $ips[$project_key]['ip'],
'referer' => $this->getReferer($ips[$project_key]['ip_area']),
'url' => $project['visit_urls'][$j],
'device_port' => $this->get_rand($this->yddzb)
];
$promises[] = $client->postAsync($project['domain'] . 'api/customerVisit', ['form_params' => $data]);
}
Utils::settle($promises)->wait();
//每个深度随机等待
sleep(rand(2, 10));
}
}
}
}
/**
* 不同项目 休眠
*/
protected function sleep($type){
if($type == 1){ //1-3个月的项目
sleep(rand(5,480));
}elseif($type == 2){ //4-8个月的项目
sleep(rand(5,240));
}elseif($type == 3){ // 大于9个月的项目
sleep(rand(5,120));
}
}
/**
* 引流的项目
*/
protected function getProjectList($type){
//todo 根据type获取需要引流的项目
return [
[
'project_id' => 1,
'domain' => 'https://demomark.globalso.com/',
]
];
}
/**
* 获取产品分类、单页和详情链接
*/
protected function getProductUrls($project_id){
//产品分类页面
$product_cate_ids = Category::where('project_id', $project_id)->where('status', Category::STATUS_ACTIVE)->pluck('id')->toArray();
$data['urls_cats'] = RouteMap::where('project_id', $project_id)->where('source', RouteMap::SOURCE_PRODUCT_CATE)->whereIn('source_id', $product_cate_ids)->get()->toArray();
//单页面
//todo 发布状态的单页面id
$data['urls_page'] = RouteMap::where('project_id', $project_id)->where('source', RouteMap::SOURCE_PAGE)->get()->toArray();
//产品详情页
$product_ids = Product::where('project_id', $project_id)->where('status', Product::STATUS_ON)->pluck('id')->toArray();
$data['urls_details'] = RouteMap::where('project_id', $project_id)->where('source', RouteMap::SOURCE_PRODUCT)->whereIn('source_id', $product_ids)->get()->toArray();
$data['urls_cats'] = array_merge($data['urls_cats'], $data['urls_page']);
if(empty($data['urls_cats'])){
$data['urls_cats'] = $data['urls_details'];
}
return $data;
}
/**
* 获取地区IP
*/
protected function getIpAreas($num)
{
//本地时间为7-23点的地区
$h = date('H');
$areas = [];
$list = DB::table('gl_area_timezone')->get();
foreach ($list as $v) {
$v = (array)$v;
$country_hour = $h + $v['diff'];
if ($country_hour < 0) {
$country_hour = 24 + $country_hour;
}
if ($country_hour >= 7 && $country_hour < 23) {
$areas[] = $v['name'];
}
}
//根据地区随机取该地区的IP
$data = DB::table('gl_xunpan_ipdata')->whereIn('ip_area', $areas)->inRandomOrder()->limit($num)->get();
return Arr::s2a(Arr::a2s($data));
}
/**
* 概率算法
*/
protected function get_rand($proArr) {
$result = '';
$proSum = array_sum($proArr);
foreach ($proArr as $key => $proCur) {
$randNum = mt_rand(1, $proSum);
if ($randNum <= $proCur) {
$result = $key;
break;
} else {
$proSum -= $proCur;
}
}
unset ($proArr);
return $result;
}
/**
* 根据随机访问深度 随机获取访问页面
*/
protected function getVisitUrls($project_urls){
//没有分类页 就只访问首页
if(!$project_urls['urls_cats']){
$url[] = $project_urls['home'];
return $url;
}
//随机访问深度
$res_sdzb = $this->get_rand($this->sdzb);
//随机访问页面类型
$res_ymzb = $this->get_rand($this->ymzb);
$all_url = array_merge($project_urls['urls_cats'],$project_urls['urls_details']);
if(!$all_url){
$url[] = $project_urls['home'];
return $url;
}
$url = [];
if($res_sdzb == 0){//深度一页
$url[] = $project_urls[$res_ymzb] ? Arr::random($project_urls[$res_ymzb])['route'] : '';
}elseif($res_sdzb == 1){//深度两页
$url[] = $project_urls['home'];
$url[] = $project_urls[$res_ymzb] ? Arr::random($project_urls[$res_ymzb])['route'] : '';
}elseif($res_sdzb == 2){//深度3-6页
$yms = rand(2,5); //随机页面数
$url = Arr::pluck(Arr::random($all_url, $yms), 'route');
$url = Arr::prepend($url, $project_urls['home']);//首页加到最前面去
}elseif($res_sdzb == 3){//深度7-11页
$yms = rand(6,10); //随机页面数
$url = Arr::pluck(Arr::random($all_url, $yms), 'route');
$url = Arr::prepend($url, $project_urls['home']);//首页加到最前面去
}
foreach ($url as &$v){
if(!Str::contains($v, $project_urls['home'])){
$v = $project_urls['home'] . $v;
}
}
return array_unique(array_filter($url));
}
/**
* 获取访问来路
*/
protected function getReferer($ip_area){
if($ip_area == '美国'){
$referer = $this->get_rand($this->lyzb);
}else{
$referer = 'https://www.google.com/';
$suffix = array_search($ip_area, $this->suffix);
if($suffix){
$res_qtzb = $this->get_rand($this->otherzb);
if($res_qtzb == 1){
$referer = 'https://www.google.'.$suffix.'/';
}
}
}
return $referer;
}
}
... ...
<?php
namespace App\Console\Commands\YesterdayCount;
use App\Helper\Common;
use App\Helper\FormGlobalsoApi;
use App\Http\Logic\Aside\Project\ProjectLogic;
use App\Models\CustomerVisit\CustomerVisitItem;
use App\Models\Project\DeployBuild;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class Yesterday extends Command
{
const STATUS_ERROR = 400;
public $error = 0;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'yesterday_count';
/**
* The console command description.
*
* @var string
*/
protected $description = '统计昨日数据';
/**
* @name :(定时执行生成昨日数据统计)handle
* @author :lyh
* @method :post
* @time :2023/5/12 14:48
*/
public function handle()
{
$deployModel = new DeployBuild();
$list = $deployModel->list();
$data = [];
$yesterday = Carbon::yesterday()->toDateString();
foreach ($list as $v){
$arr = [];
//统计时间
$arr['date'] = $yesterday;
//pv统计
$arr['pv_num'] = $this->pv_num($yesterday,$v['test_domain']);
//ip统计
$arr['ip_num'] = $this->ip_num($yesterday,$v['test_domain']);
//服务达标天数
$arr['compliance_day'] = $this->compliance_day($yesterday);
//剩余服务时常
$arr['service_day'] = $v['service_duration'] - Common::getDaysToTargetDate($v['created_at']);
//项目id
$arr['project_id'] = $v['project_id'];
$arr['created_at'] = date('Y-m-d H:i:s');
$arr['updated_at'] = date('Y-m-d H:i:s');
//询盘统计
$arr = $this->inquiry($arr,$v['test_domain']);
$data[] = $arr;
}
//判断数据是否存在
DB::table('gl_count')->insert($data);
echo $this->error;
}
/**
* @name :(统计pv)pv_num
* @author :lyh
* @method :post
* @time :2023/6/14 15:40
*/
public function pv_num($yesterday,$domain){
$pv = DB::table('gl_customer_visit_item')->whereDate('updated_date', $yesterday)->where('domain',$domain)->count();
return $pv;
}
/**
* @name :(统计pv)pv_num
* @author :lyh
* @method :post
* @time :2023/6/14 15:40
*/
public function ip_num($yesterday,$domain){
$ip = DB::table('gl_customer_visit')->whereDate('updated_date', $yesterday)->where('domain',$domain)->count();
return $ip;
}
/**
* @param $arr
* @param $domain
* @name :(询盘统计)inquiry
* @author :lyh
* @method :post
* @time :2023/6/14 15:44
*/
public function inquiry($arr,$domain){
$inquiry_list = (new FormGlobalsoApi())->getInquiryList($domain,'',1,100000000);
if($inquiry_list['status'] == self::STATUS_ERROR){
$arr['inquiry_num'] = 0;
}else{
$arr['inquiry_num'] = $inquiry_list['data']['total'];
//询盘国家统计
$countryData = $inquiry_list['data']['data'];
$countryArr = [];
foreach ($countryData as $v1){
if(isset($countryArr[$v1['country']])){
$countryArr[$v1['country']]++;
}else{
$countryArr[$v1['country']] = 0;
}
}
arsort($countryArr);
$top20 = array_slice($countryArr, 0, 20, true);
$arr['country'] = json_encode($top20);
}
return $arr;
}
/**
* @param $yesterday
* @name :(服务达标天数)compliance_day
* @author :lyh
* @method :post
* @time :2023/6/14 15:48
*/
public function compliance_day($yesterday){
//服务达标天数
$rank_info = DB::table('gl_rank_data')->where(['updated_date'=>$yesterday,'lang'=>''])->select(['compliance_day'])->first();
if(empty($rank_info)){
$compliance_day = 0;
}else{
$compliance_day = $rank_info->compliance_day;
}
return $compliance_day;
}
}
... ...
... ... @@ -16,6 +16,34 @@ class Kernel extends ConsoleKernel
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')->hourly();
$schedule->command('rank_data')->dailyAt('01:00')->withoutOverlapping(1); // 排名数据,每天凌晨执行一次
$schedule->command('rank_data_speed')->weeklyOn(1, '01:00')->withoutOverlapping(1); // 排名数据-测速数据,每周一凌晨执行一次
$schedule->command('rank_data_external_links')->weeklyOn(1, '01:00')->withoutOverlapping(1); // 排名数据-外链,每周一凌晨执行一次
$schedule->command('rank_data_indexed_pages')->weeklyOn(1, '01:00')->withoutOverlapping(1); // 排名数据-页面收录,每周一凌晨执行一次
$schedule->command('rank_data_recomm_domain')->weeklyOn(1, '01:00')->withoutOverlapping(1); // 排名数据-引荐域名,每周一凌晨执行一次
$schedule->command('rank_data_week')->weeklyOn(1, '01:00')->withoutOverlapping(1); // 排名数据,每周一凌晨执行一次
$schedule->command('share_user')->dailyAt('01:00')->withoutOverlapping(1); // 清除用户ayr_share数据,每天凌晨1点执行一次
$schedule->command('yesterday_count')->dailyAt('01:00')->withoutOverlapping(1); // 清除用户ayr_share数据,每天凌晨1点执行一次
$schedule->command('web_traffic 1')->everyThirtyMinutes(); // 引流 1-3个月的项目,半小时一次
$schedule->command('web_traffic 2')->cron('*/18 * * * *'); // 引流 4-8个月的项目,18分钟一次
$schedule->command('web_traffic 3')->cron('*/12 * * * *'); // 引流 大于9个月的项目,12分钟一次
// // 更新域名|证书结束时间,每天凌晨1点执行一次
// $schedule->command('domain_time')->dailyAt('01:00')->withoutOverlapping(1);
// // B站 - 网站数据统计
// // 获取当前月份最后一天
// $lastDay = date('Y-m-t');
// // 统计当月访问来源数据,每月最后一天23:59点执行一次
// $schedule->command('statistics_source')->monthlyOn($lastDay, '23:59')->withoutOverlapping(1);
// // 统计当月地域分布数据,每月最后一天23:59点执行一次
// $schedule->command('statistics_distribution')->monthlyOn($lastDay, '23:59')->withoutOverlapping(1);
// // 统计当月受访页面数据,每月最后一天23:59点执行一次
// $schedule->command('statistics_page')->monthlyOn($lastDay, '23:59')->withoutOverlapping(1);
// // 统计当月访问终端数据,每月最后一天23:59点执行一次
// $schedule->command('statistics_terminal')->monthlyOn($lastDay, '23:59')->withoutOverlapping(1);
// // 统计当月流量趋势数据,每月最后一天23:59点执行一次
// $schedule->command('statistics_trend')->monthlyOn($lastDay, '23:59')->withoutOverlapping(1);
// // 统计当天流量趋势数据,每天23:59点执行一次
// $schedule->command('statistics_day_trend')->dailyAt('23:59')->withoutOverlapping(1);
}
/**
... ...
... ... @@ -3,13 +3,13 @@
namespace App\Exceptions;
use App\Enums\Common\Code;
use App\Enums\Common\Common;
use App\Services\DingService;
use App\Utils\EncryptUtils;
use App\Utils\LogUtils;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Route;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
... ... @@ -59,7 +59,6 @@ class Handler extends ExceptionHandler
*/
public function report(Throwable $exception)
{
//日志记录
$exceptionMessage = "错误CODE:" . $exception->getCode() .
"-----错误message:" . $exception->getMessage() .
... ... @@ -111,31 +110,26 @@ class Handler extends ExceptionHandler
$code = $exception->getCode();
}elseif ($exception instanceof BsideGlobalException) {
$code = $exception->getCode();
} elseif ($exception instanceof ValidationException) {
}elseif ($exception instanceof ValidationException) {
$code = Code::USER_PARAMS_ERROE();
$message = Arr::first(Arr::first($exception->errors()));
$message = $code->description = Arr::first(Arr::first($exception->errors()));
} elseif ($exception instanceof NotFoundHttpException || $exception instanceof MethodNotAllowedHttpException) {
return response('404 Not Found', 404);
} else {
$code = Code::SYSTEM_ERROR();
}
//钉钉通知错误信息
if (in_array(config('app.env'), ['test', 'production']) && (in_array(substr($code, 0, 1), ['B', 'C']))) {
$exceptionMessage = "路由:" . Route::current()->uri .
"-----错误CODE:" . $exception->getCode() .
"-----错误message:" . $exception->getMessage() .
'------错误文件:' . $exception->getFile() . '-------错误行数:' .
$exception->getLine();
(new DingService())->handle(['keyword' => "ERROR", 'msg' => config('app.env') . '环境报错:' . $exceptionMessage, 'isAtAll' => false]);
}
//开启debug 错误原样输出
$debub = config('app.debug');
$message = $debub ? $message : ($code->description ?? $message);
$response = [
'code' => $code,
'message' => $message
];
// 调试模式
if(env('app_debug')){
$response['trace'] = $exception->getTrace();
}
//加密返回
if (config('app.params_encrypt')) {
$k = config('app.params_encrypt_key');
... ...
<?php
namespace App\Files;
use Illuminate\Http\Request;
class Image
{
protected $request = [];
public function __construct(Request $request)
{
$this->request = $request;
}
/**
* @name :上传图片
* @return void
* @author :liyuhang
* @method
*/
public function uploads(){
$url = './uploads/images/';
$param = $this->request->post();
if($this->request->hasFile('image') && $this->request->file('image')->isValid()){
$filename = date('ymdHis').rand(10000,99999).$this->request->file('image');
$this->request->file('image')->move('./uploads/images/',$filename);
}else{
return false;
}
return $url.$filename;
}
}
<?php
namespace App\Helper;
class AliSms
{
private $_msg = array( //状态对照
1 => "发送成功",
0 => "其他系统错误",
-1 => "短信余额不足",
-2 => "资金账户被锁定",
-3 => "用户被锁定",
-4 => "号码在黑名单内",
-5 => "用户名或密码不正确",
-6 => "号码不正确",
-7 => "接口连接失败",
-8 => "号码格式错误",
-9 => "通道编号错误",
-10 => "定时发送时间不正确",
-11 => "没有输入短信内容",
-12 => "短信内容超出长度限制",
-15 => "内容含非法关键字",
-16 => "超出发送时间范围",
-17 => "通道被关闭",
-18 => "短信内容没有签名",
-30 => "手机未认证",
-31 => "身份未认证",
-32 => "请勿重复发送",
-33 => "验证码已过期,请重新获取",
-34 => "手机号码格式不正确",
-35 => "验证码不正确",
);
// 保存错误信息
public $error;
public $_code = "";
public $_name = "";
public $_key_str = ""; // cache full name.
protected $_expire = 600; // 验证码过期时间(s)
public $_key = [
];
// Access Key ID
private $accessKeyId = '';
// Access Key Secret
private $accessKeySecret = '';
// 签名
private $signName = '';
// 模版ID
public $templateCode = '';
public function __construct($config = array())
{
$config = array(
'accessKeyId' => config('aliyunsms.access_key'),
'accessKeySecret' => config('aliyunsms.access_secret'),
'signName' => config('aliyunsms.sign_name'),
'templateCode' => config('aliyunsms.login_sms_temp'),
);
// 配置参数
$this->accessKeyId = $config['accessKeyId'];
$this->accessKeySecret = $config['accessKeySecret'];
$this->signName = $config['signName'];
$this->templateCode = $config['templateCode'];
}
/**
* 规范化字符串以符合阿里云短信接口
* @param $string
* @return mixed|string
*/
private function percentEncode($string)
{
$string = urlencode($string);
$string = preg_replace('/\+/', '%20', $string);
$string = preg_replace('/\*/', '%2A', $string);
$string = preg_replace('/%7E/', '~', $string);
return $string;
}
/**
* 签名
*
* @param unknown $parameters
* @param unknown $accessKeySecret
* @return string
*/
private function computeSignature($parameters, $accessKeySecret)
{
ksort($parameters);
$canonicalizedQueryString = '';
foreach ($parameters as $key => $value) {
$canonicalizedQueryString .= '&' . $this->percentEncode($key) . '=' . $this->percentEncode($value);
}
$stringToSign = 'GET&%2F&' . $this->percentencode(substr($canonicalizedQueryString, 1));
$signature = base64_encode(hash_hmac('sha1', $stringToSign, $accessKeySecret . '&', true));
return $signature;
}
/**
* 发送验证码 https://help.aliyun.com/document_detail/44364.html?spm=5176.doc44368.6.126.gSngXV
*
* @param unknown $mobile
* @param unknown $verify_code
*
*/
public function send_sms($mobile, $paramstring)
{
$params = array(
// 公共参数
'SignName' => $this->signName,
'Format' => 'JSON',
'Version' => '2016-09-27',
'AccessKeyId' => $this->accessKeyId,
'SignatureVersion' => '1.0',
'SignatureMethod' => 'HMAC-SHA1',
'SignatureNonce' => uniqid(),
'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
// 接口参数
'Action' => 'SingleSendSms',
'TemplateCode' => $this->templateCode,
'RecNum' => $mobile,
'ParamString' => $paramstring,
);
// 计算签名并把签名结果加入请求参数
$params['Signature'] = $this->computeSignature($params, $this->accessKeySecret);
// 发送请求
$url = 'https://sms.aliyuncs.com/?' . http_build_query($params);
$result = http_get($url); //TODO:上线前打开
if (isset($result['Code'])) {
$this->error = $this->getErrorMessage($result['Code']);
return false;
}
return true;
}
/**
* 发送验证码 https://help.aliyun.com/document_detail/44364.html?spm=5176.doc44368.6.126.gSngXV
*
* @param unknown $mobile
* @param unknown $verify_code
*
*/
public function send_verify($mobile)
{
if ($this->checkMobile($mobile) === false) {
$this->error = $this->_msg[-34];
return -34;
}
$session = cache($this->_key_str . $mobile);
if ($session && time() - $session['time'] < 60) {
if ($session['code'] == null) {
return true;
} else {
$this->error = $this->_msg[-32];
return -32;
}
}
$this->_code = rand(1000, 9999);
$params = array(
// 公共参数
'SignName' => $this->signName,
'Format' => 'JSON',
'Version' => '2016-09-27',
'AccessKeyId' => $this->accessKeyId,
'SignatureVersion' => '1.0',
'SignatureMethod' => 'HMAC-SHA1',
'SignatureNonce' => uniqid(),
'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
// 接口参数
'Action' => 'SingleSendSms',
'TemplateCode' => $this->templateCode,
'RecNum' => $mobile,
'ParamString' => '{"msgcode":"' . $this->_code . '"}',
);
// 计算签名并把签名结果加入请求参数
$params['Signature'] = $this->computeSignature($params, $this->accessKeySecret);
// 发送请求
$url = 'https://sms.aliyuncs.com/?' . http_build_query($params);
$result = http_get($url); //TODO:上线前打开
// $result =1;
if ($result) {
$session = array();
$session['code'] = $this->_code; // 把校验码保存到session
$session['time'] = time(); // 验证码创建时间
cache($this->_key_str . $mobile, $session, $this->_expire);
} else {
return $this->error = $this->_msg[0];
}
if (isset($result['Code'])) {
$this->error = $this->getErrorMessage($result['Code']);
return false;
}
return true;
}
/**
* 验证手机号码
*/
public function checkMobile($tel)
{
if (preg_match("/^1[3,4,6,5,8,7,9][0-9]{1}[0-9]{8}$/", $tel)) {
//验证通过
return true;
} else {
$this->error = $this->_msg[-34];
//手机号码格式不对
return false;
}
}
/**
* 验证码是否正确
* @param string $key 手机号码
* @param int|string $code 验证码
* @param int|string $type 类型 reg-注册时获取 sms-快速登录时 pwd-修改密码时 bind-绑定手机时 unbind-解绑时
* @return boolean 验证短信验证码是否正确
*/
public function check($key, $code, $type = 'reg')
{
$this->_key_str = $type . '_' . $key;
$session = cache($this->_key_str);
if (empty($code) || empty($session)) {
$this->error = $this->_msg[-33] . $this->_key_str;
return false;
}
if (time() - $session['time'] > $this->_expire) {
cache($this->_key_str, null);
$this->error = $this->_msg[-33] . $this->_key_str;
return false;
}
if ($code == $session['code']) {
return true;
}
$this->error = $this->_msg[-35] . $this->_key_str;
return false;
}
/**
* 验证成功后调用清空验证码
*/
public function afterCheck()
{
cache($this->_key_str, null);
}
/**
* 获取详细错误信息
*
* @param unknown $status
*/
public function getErrorMessage($status)
{
$message = array(
'InvalidDayuStatus.Malformed' => '账户短信开通状态不正确',
'InvalidSignName.Malformed' => '短信签名不正确或签名状态不正确',
'InvalidTemplateCode.MalFormed' => '短信模板Code不正确或者模板状态不正确',
'InvalidRecNum.Malformed' => '目标手机号不正确,单次发送数量不能超过100',
'InvalidParamString.MalFormed' => '短信模板中变量不是json格式',
'InvalidParamStringTemplate.Malformed' => '短信模板中变量与模板内容不匹配',
'InvalidSendSms' => '1小时只能请求7次,谢谢',
'InvalidDayu.Malformed' => '变量不能是url,可以将变量固化在模板中',
);
if (isset($message[$status])) {
return $message[$status];
}
return $status;
}
private function _addlog($name, $title)
{
$this->_keys["code"] = $this->_code;
// addlog($this->_keys, $title, 1, $this->_url);
}
}
... ...
... ... @@ -3,6 +3,8 @@
namespace App\Helper;
use Illuminate\Support\Collection;
/**
* 数组类函数
* Class Arrays
... ... @@ -125,4 +127,89 @@ class Arr extends \Illuminate\Support\Arr
return $signle ? $rows[0] : $rows;
}
/**
* 数组转字符串
* @param $arr
* @return string
* @author zbj
* @date 2023/4/17
*/
public static function a2s($arr): string
{
return json_encode($arr, JSON_UNESCAPED_UNICODE);
}
/**
* 字符串转数组
* @param $str
* @return array|mixed
* @author zbj
* @date 2023/4/17
*/
public static function s2a($str)
{
if (is_array($str)) {
return $str;
}
return is_object($str) ? (array)$str : json_decode($str, true);
}
/**
* 数组转set形式字符串
* @param $arr
* @param string $format
* @return string
* @author zbj
* @date 2023/4/17
*/
public static function arrToSet($arr, string $format = 'intval'): string
{
$arr = array_unique(array_filter(Arr::splitFilterToArray($arr, $format, ',')));
return $arr ? implode(',', $arr) : '';
}
/**
* set形式字符串转数组
* @param $str
* @param string $format
* @return array
* @author zbj
* @date 2023/4/17
*/
public static function setToArr($str, string $format = 'intval')
{
if (is_string($str)) {
return Arr::splitFilterToArray($str, $format, ',');
}
return $str ?: [];
}
/**
* 将数组设置成某个键的值
* @param $arr
* @param $key
* @return array
* @author zbj
* @date 2023/5/16
*/
public static function setValueToKey($arr, $key)
{
$data = [];
if (!$arr) {
return $data;
}
foreach ($arr as $v) {
$data[$v[$key]] = $v;
}
if ($arr instanceof Collection) {
$data = new Collection($data);
}
return $data;
}
}
... ...
<?php
namespace App\Helper;
use GuzzleHttp\Client;
/**
* @name: ayr_share社交绑定
*/
class AyrShare
{
public $path = 'https://app.ayrshare.com';
//api_key
public $api_key = 'G8GQW3X-XBTMGXW-QPDDZ9A-WE1Z5SB';
//系统设置
public $config = [
'facebook'=>'#best https://www.facebook.com',
'google'=>'#best https://www.google.com',
'instagram'=>'#best https://www.instagram.com',
'linkedin'=>'#best https://www.linkedin.com',
'twitter'=>'#best https://www.twitter.com',
'telegram'=>'#best https://www.telegram.com',
'tiktok'=>'#bestvideo',
];
//profile_key
public $profile_key = '';
//设置请求头
public $headers = [
'Authorization' => 'Bearer ',
'Content-Type' => 'application/json',
];
//私钥
private $private_key = "-----BEGIN RSA PRIVATE KEY-----
MIICWgIBAAKBgGFatMeBeaw7QJrqmylMLZlwuuO0FA/EZg5/g7Rrqu+FgpwvFkJq
9twEZJY+aIdDH8/RVrCZQGR/xUxKw9v4ows+sLwi4g41m8KRKDXUcJwQvSlwsHAi
h9hPGZxDsRK0Nv4pZ7XqGgh0Wb0VypX/+Q1dhX9BnXQmvEKayk8GQWQxAgMBAAEC
gYAFqOJNnudV7fPpja4LjpQwEW+sATIRYJeWTC9587ByUE6xicM/hTxouhCm82Xc
Rzi4OjFR/vbRYOQ1dTtBtIi18fdRrseQNyR/N2NZjw1X8n5aZcw5NVaa3d3YTQNa
uzjnYF5eYSOD4pNKKIDc35VHdmvGCV/JXwQKMTgu1+4AAQJBAL5jjN3kvMKFF8vG
DyYR8k+wPG9iXAdR0HjVNB3OzxKVW0MTwM32pJBXCmF1MOziL8WC48VHQL48hVRa
52xRqAECQQCC53rrrOPhPCLIb6kBfgqnxCojqlUK9paFL7NYTPtLYcOajY6+NiKT
CG1gaOwZh4r34HF7I59l/Ds98Z4nQDwxAkAC4/oIiGeBQIoK8vfZ6R3XreJNAp5J
EinrG7mN1kz4iEH5c7xSpDL9agTjU+cpQYneIs2Yeit2d+7CSBsJXvgBAkBDFsfU
yYLxCJT7DN8dOK/VU6AVL1Luj3qNP+k2tB2GgNBzAWHK8ou9t2/3HU8DtofuikUe
yx8Cccca9B4OF8nBAkAgIUZKGmVNFcGnFFo55vSJInNXFo4HCJ2o4DunBORVtQ/j
zFePUMXy1bFghAfzNKlrc5XgH4ixeeMh3cDtU97K
-----END RSA PRIVATE KEY-----";
/**
* @name :(创建子账户配置文件)post_create_profiles
* @author :lyh
* @method :post
* @time :2023/5/5 15:16
*/
public function post_create_profiles($data){
$param = [
'title'=>$data['title'],
];
$url = $this->path.'/api/profiles/profile';
return $this->http_click('post',$url,$param);
}
/**
* @name :(删除子账户配置文件)deleted_profiles
* @author :lyh
* @method :post
* @time :2023/5/5 15:16
*/
public function deleted_profiles($data){
$param = [
// 'title'=>$data['title'],
'profileKey'=>$data['profileKey'],
];
$url = $this->path.'/api/profiles/profile';
return $this->http_click('delete',$url,$param);
}
/**
* @name :(跳转第三方生成jwt令牌)post_generate_jwt
* @author :lyh
* @method :post
* @time :2023/5/5 18:07 https://app.ayrshare.com/api/profiles/generateJWT
*/
public function post_generate_jwt($data,$domain = 'globalso'){
$param = [
'domain'=>$domain,
'privateKey'=>$this->private_key,
'profileKey'=>$data['profileKey'],
'logout'=>true
];
$url = $this->path.'/api/profiles/generateJWT';
return $this->http_click('post',$url,$param);
}
/**
* @name :(获取指定api_key的配置文件)get_profiles_users
* @author :lyh
* @method :post
* @time :2023/5/6 16:44
*/
public function get_profiles_users($api_key){
$this->headers['Authorization'] = $this->headers['Authorization'].$api_key;
$url = $this->path.'/api/user';
return $this->http_click('get',$url,[],$this->headers);
}
/**
* @name :(发帖)post_send_msg
* @author :lyh
* @method :post
* @time :2023/5/8 9:22
* @param :platforms: "facebook", "fbg", "twitter",
* "linkedin", "instagram","youtube", "reddit" ,"telegram""
*/
public function post_send_msg($param,$api_key){
//平台参数处理
$param['idempotencyKey'] = uniqid().time();
$url = $this->path.'/api/post';
return $this->http_post_ayr($url,$param,$api_key);
}
public function http_post_ayr($url,$param,$api_key){
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => http_build_query($param),
CURLOPT_HTTPHEADER => array(
'Authorization: Bearer '.$api_key,
'Accept-Encoding: gzip'
),
));
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
/**
* @name :(上传图片或视频到ayr_share)post_media_upload
* @author :lyh
* @method :post
* @time :2023/5/8 9:47
* https://app.ayrshare.com/api/media/upload
*/
public function post_media_upload($data,$api_key){
$param = [
'file'=>$data['file'],//base64编码
];
$this->headers['Authorization'] = $this->headers['Authorization'].$api_key;
$url = $this->path.'/api/media/upload';
return $this->http_click('post',$url,$param,$this->headers);
}
/**
* @name :获取过去30天发布的历史记录(1-30)
* @author :lyh
* @method :get
* @time :2023/5/5 10:00
*/
public function get_analytics_links($to_day){
$last_days = (string)$to_day;
$url = $this->path.'/analytics/links?lastDays='.$last_days;
return $this->http_click('get',$url);
}
/**
* @name :(通过 Ayrshare 获取给定帖子的实时分析,例如点赞、印象、转推等)post_analytics
* @author :lyh
* @method :post
* @time :2023/5/5 11:56
*/
public function post_analytics($id){
$param = [
'id'=>$id,
'platforms' => ['facebook', 'instagram', 'twitter', 'linkedin', 'pinterest', 'youtube', 'tiktok'],
];
$url = $this->path.'/api/analytics/post';
return $this->http_click('post', $url, $param);
}
/**
* @name :(获取特定用户个人资料)analytics_post
* @author :lyh
* @method :post
* @time :2023/5/5 10:43
*/
public function post_analytics_social(){
$post_data = [
'platforms' => ['facebook', 'instagram', 'twitter', 'linkedin', 'pinterest', 'youtube', 'tiktok'],
];
$url = $this->path.'/api/analytics/social';
return $this->http_click('post',$url,$post_data);
}
/**
* @name :(设置自动计划)post_schedule_set
* @author :lyh
* @method :post
* @time :2023/5/5 13:58
*/
public function post_schedule_set($data){
$param = [
'schedule'=>["13:05Z", "20:14Z"],
'title'=>$data['title'],
];
$url = $this->path.'/api/auto-schedule/set';
return $this->http_click('post',$url,$param);
}
/**
* @name :(删除自动计划)delete_schedule
* @author :lyh
* @method :post
* @time :2023/5/5 14:04
*/
public function delete_schedule($data){
$param = [
'title'=>$data['title'],
];
$url = $this->path.'/api/auto-schedule/delete';
return $this->http_click('delete',$url,$param);
}
/**
* @name :(列出自动计划)get_schedule_list
* @author :lyh
* @method :post
* @time :2023/5/5 14:08
*/
public function get_schedule_list(){
$url = $this->path.'/api/auto-schedule/list';
return $this->http_click('get',$url);
}
/**
* @name :(发布到用户个人资料)post_user
* @author :lyh
* @method :post
* @time :2023/5/5 15:00
*/
public function post_profiles($data){
$param = [
'post'=>$data['post'],
'platforms'=>$data['platforms'],
'profileKey'=>$this->profile_key,
'mediaUrls'=>$data['mediaUrls']
];
$url = $this->path.'/api/post';
return $this->http_click('post',$url,$param);
}
/**
* 发送http post,get,put,delete请求
* @param type $url
* @param type $post_data
*/
function http_click($method = 'post',$url, $param = [],$header = [])
{
if(!empty($param)){
$post_data['json'] = $param;
}
if(empty($header)){
$this->headers['Authorization'] = $this->headers['Authorization'].$this->api_key;
}
$post_data['headers'] = !empty($header) ? $header : $this->headers;
$client = new Client();
try {
$res = $client->request(strtoupper($method), $url, $post_data)->getBody()->getContents();
return (array)json_decode($res);
} catch (\Exception $e) {
return ["status"=>"fail","message"=>$e->getMessage()];
}
}
}
... ...
<?php
namespace App\Helper;
use App\Models\Ai\AiCommand as AiCommandModel;
use App\Models\User\UserLog as UserLogModel;
use App\Models\User\UserLogin as UserLoginModel;
use Illuminate\Support\Facades\Cache;
/**
* @name:
*/
class Common
{
/**
* @name :生成用户操作日志
* @return void
* @author :liyuhang
* @method
*/
public static function set_user_log($param = []){
$data = [
'operator_id'=>$param['operator_id'],
'model'=>$param['model'],
'remark'=>$param['remark']
];
$model = new UserLogModel();
return $model->add($data);
}
/**
* @name :写入登录日志
* @return void
* @author :liyuhang
* @method
*/
public static function set_user_login($param = []){
$data = [
'user_id'=>$param['user_id'],
'ip'=>$param['ip']
];
$model = new UserLoginModel();
return $model->add($data);
}
/**
* @name :ai自动生成
* @return mixed
* @author :liyuhang
* @method
*/
public static function send_openai_msg($url,$param){
$url = HTTP_OPENAI_URL.$url;
$aiCommandModel = New AiCommandModel();
//指定库获取指令
$info = $aiCommandModel->read(['key'=>$param['key']]);
if($info === false){
response('指令不存在',400);
}
//替换关键字
$content = str_replace('$keyword$', $param['keywords'], $info['ai']);
$data = [
'messages'=>[
['role'=>'system','content'=>$info['scene']],
['role'=>'assistant','content'=>$content],
]
];
return http_post($url,json_encode($data));
}
/**
* @name :获取缓存
* @return void
* @author :liyuhang
* @method
*/
public static function get_user_cache($table,$id,$type = 'B'){
$data = [];
$cache = config('cache.user_is_cache');
if(isset($cache) && ($cache['is_cache'] == true)){
$key = 'cache_'.$table.'_'.$id.'_type';
$data = Cache::store('file')->get($key);
}
return $data;
}
/**
* @name :写入缓存
* @return bool
* @author :liyuhang
* @method
*/
public static function set_user_cache($data = [],$table,$id,$type = 'B'){
$cache = config('cache.user_is_cache');
if(isset($cache) && ($cache['is_cache'] == true)){
$key = 'cache_'.$table.'_'.$id.'_type';
Cache::store('file')->set($key,$data,3600);
}
return true;
}
/**
* @name :清除缓存
* @return bool
* @author :liyuhang
* @method
*/
public static function del_user_cache($table,$id,$type = 'B'){
$cache = config('cache.user_is_cache');
if(isset($cache) && ($cache['is_cache'] == true)){
if(is_array($id)){
foreach ($id as $v){
$key = 'cache_'.$table.'_'.$v.'_type';
Cache::store('file')->pull($key);
}
}else{
$key = 'cache_'.$table.'_'.$id.'_type';
}
Cache::store('file')->pull($key);
}
return true;
}
/**
* @name :(多维数组去重)array_deduplication
* @author :lyh
* @method :post
* @time :2023/5/9 10:47
*/
public static function uniqueMultiArray($arr) {
$arr = array_map('serialize', $arr);
$arr = array_unique($arr);
$arr = array_map('unserialize', $arr);
return $arr;
}
/**
* @param $targetDateTime
* @name :(获取时间差,精确时分秒,返回天数)getDaysToTargetDate
* @author :lyh
* @method :post
* @time :2023/5/24 9:38
*/
public static function getDaysToTargetDate($targetDateTime)
{
$currentTimestamp = time();
$targetTimestamp = strtotime($targetDateTime);
$days = floor(($currentTimestamp - $targetTimestamp) / (60 * 60 * 24));
return (int)$days;
}
}
... ...
<?php
namespace App\Helper;
use App\Models\WebSetting\WebSettingCountry;
/**
* @name:多语言国家设置
*/
class Country
{
public $tls_list = [
'en' => [
'text' => '英语',
'lang_text' => 'English',
'con_flag' => 'con_flag/en.jfif',
'shop_lang' => 'en-gb',
],
'zh' => [
'text' => '中文',
'lang_text' => '简体中文',
'con_flag' => 'con_flag/zh.jfif',
'shop_lang' => 'zh-cn',
],
'fr' => [
'text' => '法语',
'lang_text' => 'En français',
'con_flag' => '',
],
'de' => [
'text' => '德语',
'lang_text' => 'Das ist Deutsch.',
'con_flag' => '',
],
'ko' => [
'text' => '韩语',
'lang_text' => '',
'con_flag' => '',
],
'ja' => [
'text' => '日语',
'lang_text' => '',
'con_flag' => '',
],
'es' => [
'text' => '西班牙语',
'lang_text' => 'Español.',
'con_flag' => '',
],
'ar' => [
'text' => '阿拉伯语',
'lang_text' => '',
'con_flag' => '',
],
'pt' => [
'text' => '葡萄牙语(葡萄牙、巴西)',
'lang_text' => 'Língua portuguesa',
'con_flag' => '',
],
'ru' => [
'text' => '俄语',
'lang_text' => '',
'con_flag' => '',
],
'af' => [
'text' => '南非荷兰语',
'lang_text' => '',
'con_flag' => '',
],
'sq' => [
'text' => '阿尔巴尼亚语',
'lang_text' => '',
'con_flag' => '',
],
'am' => [
'text' => '阿姆哈拉语',
'lang_text' => '',
'con_flag' => '',
],
'hy' => [
'text' => '亚美尼亚语',
'lang_text' => '',
'con_flag' => '',
],
'az' => [
'text' => '阿塞拜疆语',
'lang_text' => '',
'con_flag' => '',
],
'eu' => [
'text' => '巴斯克语',
'lang_text' => '',
'con_flag' => '',
],
'be' => [
'text' => '白俄罗斯语',
'lang_text' => '',
'con_flag' => '',
],
'bn' => [
'text' => '孟加拉语',
'lang_text' => '',
'con_flag' => '',
],
'bs' => [
'text' => '波斯尼亚语',
'lang_text' => '',
'con_flag' => '',
],
'bg' => [
'text' => '保加利亚语',
'lang_text' => '',
'con_flag' => '',
],
'ca' => [
'text' => '加泰罗尼亚语',
'lang_text' => '',
'con_flag' => '',
],
'ceb' => [
'text' => '宿务语',
'lang_text' => '',
'con_flag' => '',
],
'cn' => [
'text' => '中文(简体)',
'lang_text' => '简体中文',
'con_flag' => 'con_flag/zh.jfif',
'shop_lang' => 'zh-cn',
],
'tw' => [
'text' => '中文(繁体)',
'lang_text' => '繁体中文',
'con_flag' => 'con_flag/zh.jfif',
],
'co' => [
'text' => '科西嘉语',
'lang_text' => '',
'con_flag' => '',
],
'hr' => [
'text' => '克罗地亚语',
'lang_text' => '',
'con_flag' => '',
],
'cs' => [
'text' => '捷克语',
'lang_text' => '',
'con_flag' => '',
],
'da' => [
'text' => '丹麦语',
'lang_text' => '',
'con_flag' => '',
],
'nl' => [
'text' => '荷兰语',
'lang_text' => '',
'con_flag' => '',
],
'eo' => [
'text' => '世界语',
'lang_text' => '',
'con_flag' => '',
],
'et' => [
'text' => '爱沙尼亚语',
'lang_text' => '',
'con_flag' => '',
],
'fi' => [
'text' => '芬兰语',
'lang_text' => '',
'con_flag' => '',
],
'fy' => [
'text' => '弗里斯兰语',
'lang_text' => '',
'con_flag' => '',
],
'gl' => [
'text' => '加利西亚语',
'lang_text' => '',
'con_flag' => '',
],
'ka' => [
'text' => '格鲁吉亚语',
'lang_text' => '',
'con_flag' => '',
],
'el' => [
'text' => '希腊语',
'lang_text' => '',
'con_flag' => '',
],
'gu' => [
'text' => '古吉拉特语',
'lang_text' => '',
'con_flag' => '',
],
'ht' => [
'text' => '海地克里奥尔语',
'lang_text' => '',
'con_flag' => '',
],
'ha' => [
'text' => '豪萨语',
'lang_text' => '',
'con_flag' => '',
],
'haw' => [
'text' => '夏威夷语',
'lang_text' => '',
'con_flag' => '',
],
'iw' => [
'text' => '希伯来语',
'lang_text' => '',
'con_flag' => '',
],
'hi' => [
'text' => '印地语',
'lang_text' => '',
'con_flag' => '',
],
'hmn' => [
'text' => '苗语',
'lang_text' => '',
'con_flag' => '',
],
'hu' => [
'text' => '匈牙利语',
'lang_text' => '',
'con_flag' => '',
],
'is' => [
'text' => '冰岛语',
'lang_text' => '',
'con_flag' => '',
],
'ig' => [
'text' => '伊博语',
'lang_text' => '',
'con_flag' => '',
],
'id' => [
'text' => '印度尼西亚语',
'lang_text' => 'Bahasa Indonesia',
'con_flag' => 'con_flag/id.jfif',
'shop_lang' => 'id',
],
'ga' => [
'text' => '爱尔兰语',
'lang_text' => '',
'con_flag' => '',
],
'it' => [
'text' => '意大利语',
'lang_text' => 'Lingua italiana',
'con_flag' => '',
],
'jw' => [
'text' => '爪哇语',
'lang_text' => '',
'con_flag' => '',
],
'kn' => [
'text' => '卡纳达语',
'lang_text' => '',
'con_flag' => '',
],
'kk' => [
'text' => '哈萨克语',
'lang_text' => '',
'con_flag' => '',
],
'km' => [
'text' => '高棉语',
'lang_text' => '',
'con_flag' => '',
],
'rw' => [
'text' => '卢旺达语',
'lang_text' => '',
'con_flag' => '',
],
'ku' => [
'text' => '库尔德语',
'lang_text' => '',
'con_flag' => '',
],
'ky' => [
'text' => '吉尔吉斯语',
'lang_text' => '',
'con_flag' => '',
],
'lo' => [
'text' => '老挝文',
'lang_text' => '',
'con_flag' => '',
],
'la' => [
'text' => '拉丁文',
'lang_text' => '',
'con_flag' => '',
],
'lv' => [
'text' => '拉脱维亚语',
'lang_text' => '',
'con_flag' => '',
],
'lt' => [
'text' => '立陶宛语',
'lang_text' => '',
'con_flag' => '',
],
'lb' => [
'text' => '卢森堡语',
'lang_text' => '',
'con_flag' => '',
],
'mk' => [
'text' => '马其顿语',
'lang_text' => '',
'con_flag' => '',
],
'mg' => [
'text' => '马尔加什语',
'lang_text' => '',
'con_flag' => '',
],
'ms' => [
'text' => '马来语',
'lang_text' => 'Bahasa Melayu',
'con_flag' => 'con_flag/ms.jfif',
'shop_lang' => 'ms-my',
],
'ml' => [
'text' => '马拉雅拉姆文',
'lang_text' => '',
'con_flag' => '',
],
'mt' => [
'text' => '马耳他语',
'lang_text' => '',
'con_flag' => '',
],
'mi' => [
'text' => '毛利语',
'lang_text' => '',
'con_flag' => '',
],
'mr' => [
'text' => '马拉地语',
'lang_text' => '',
'con_flag' => '',
],
'mn' => [
'text' => '蒙古文',
'lang_text' => '',
'con_flag' => '',
],
'my' => [
'text' => '缅甸语',
'lang_text' => '',
'con_flag' => '',
],
'ne' => [
'text' => '尼泊尔语',
'lang_text' => '',
'con_flag' => '',
],
'no' => [
'text' => '挪威语',
'lang_text' => '',
'con_flag' => '',
],
'ny' => [
'text' => '尼杨扎语(齐切瓦语)',
'lang_text' => '',
'con_flag' => '',
],
'or' => [
'text' => '奥里亚语(奥里亚)',
'lang_text' => '',
'con_flag' => '',
],
'ps' => [
'text' => '普什图语',
'lang_text' => '',
'con_flag' => '',
],
'fa' => [
'text' => '波斯语',
'lang_text' => '',
'con_flag' => '',
],
'pl' => [
'text' => '波兰语',
'lang_text' => '',
'con_flag' => '',
],
'pa' => [
'text' => '旁遮普语',
'lang_text' => '',
'con_flag' => '',
],
'ro' => [
'text' => '罗马尼亚语',
'lang_text' => '',
'con_flag' => '',
],
'sm' => [
'text' => '萨摩亚语',
'lang_text' => '',
'con_flag' => '',
],
'gd' => [
'text' => '苏格兰盖尔语',
'lang_text' => '',
'con_flag' => '',
],
'sr' => [
'text' => '塞尔维亚语',
'lang_text' => '',
'con_flag' => '',
],
'st' => [
'text' => '塞索托语',
'lang_text' => '',
'con_flag' => '',
],
'sn' => [
'text' => '修纳语',
'lang_text' => '',
'con_flag' => '',
],
'sd' => [
'text' => '信德语',
'lang_text' => '',
'con_flag' => '',
],
'si' => [
'text' => '僧伽罗语',
'lang_text' => '',
'con_flag' => '',
],
'sk' => [
'text' => '斯洛伐克语',
'lang_text' => '',
'con_flag' => '',
],
'sl' => [
'text' => '斯洛文尼亚语',
'lang_text' => '',
'con_flag' => '',
],
'so' => [
'text' => '索马里语',
'lang_text' => '',
'con_flag' => '',
],
'su' => [
'text' => '巽他语',
'lang_text' => '',
'con_flag' => '',
],
'sw' => [
'text' => '斯瓦希里语',
'lang_text' => '',
'con_flag' => '',
],
'sv' => [
'text' => '瑞典语',
'lang_text' => '',
'con_flag' => '',
],
'tl' => [
'text' => '塔加路语(菲律宾语)',
'lang_text' => 'Pilipino',
'con_flag' => 'con_flag/tl.jfif',
'shop_lang' => 'tl',
],
'tg' => [
'text' => '塔吉克语',
'lang_text' => '',
'con_flag' => '',
],
'ta' => [
'text' => '泰米尔语',
'lang_text' => '',
'con_flag' => '',
],
'tt' => [
'text' => '鞑靼语',
'lang_text' => '',
'con_flag' => '',
],
'te' => [
'text' => '泰卢固语',
'lang_text' => '',
'con_flag' => '',
],
'th' => [
'text' => '泰文',
'lang_text' => 'ไทย',
'con_flag' => 'con_flag/th.jfif',
'shop_lang' => 'th',
],
'tr' => [
'text' => '土耳其语',
'lang_text' => '',
'con_flag' => '',
],
'tk' => [
'text' => '土库曼语',
'lang_text' => '',
'con_flag' => '',
],
'uk' => [
'text' => '乌克兰语',
'lang_text' => '',
'con_flag' => '',
],
'ur' => [
'text' => '乌尔都语',
'lang_text' => '',
'con_flag' => '',
],
'ug' => [
'text' => '维吾尔语',
'lang_text' => '',
'con_flag' => '',
],
'uz' => [
'text' => '乌兹别克语',
'lang_text' => '',
'con_flag' => '',
],
'vi' => [
'text' => '越南语',
'lang_text' => '',
'con_flag' => '',
],
'cy' => [
'text' => '威尔士语',
'lang_text' => '',
'con_flag' => '',
],
'xh' => [
'text' => '班图语',
'lang_text' => '',
'con_flag' => '',
],
'yi' => [
'text' => '意第绪语',
'lang_text' => '',
'con_flag' => '',
],
'yo' => [
'text' => '约鲁巴语',
'lang_text' => '',
'con_flag' => '',
],
'zu' => [
'text' => '祖鲁语',
'lang_text' => '',
'con_flag' => '',
],
];
/**
* @name :(获取翻译国家)set_country
* @author :lyh
* @method :post
* @time :2023/5/4 17:57
*/
public function set_country(){
$data = [];
foreach ($this->tls_list as $k=>$v){
$data[] = ['name'=>$v['text'],'alias'=>$k,'image'=>$k.'.png','con_flag'=>$v['con_flag'],'lang_text'=>$v['lang_text']];
}
$webCountry = new WebSettingCountry();
$webCountry->insert($data);
return true;
}
}
... ...
<?php
namespace App\Helper;
/**
* 计算文件hash
*
* 七牛云的计算规则
*/
class FileEtag
{
const BLOCK_SIZE = 4194304; //4*1024*1024 分块上传块大小,该参数为接口规格,不能修改
private static function packArray($v, $a)
{
return call_user_func_array('pack', array_merge(array($v), (array)$a));
}
private static function blockCount($fsize)
{
return intval(($fsize + (self::BLOCK_SIZE - 1)) / self::BLOCK_SIZE);
}
private static function calcSha1($data)
{
$sha1Str = sha1($data, true);
$err = error_get_last();
if ($err !== null) {
return array(null, $err);
}
$byteArray = unpack('C*', $sha1Str);
return array($byteArray, null);
}
private static function base64_urlSafeEncode($data)
{
$find = array('+', '/');
$replace = array('-', '_');
return str_replace($find, $replace, base64_encode($data));
}
public static function sum($filename)
{
$fhandler = fopen($filename, 'r');
$err = error_get_last();
if ($err !== null) {
return array(null, $err);
}
$fstat = fstat($fhandler);
$fsize = $fstat['size'];
if ((int)$fsize === 0) {
fclose($fhandler);
return array('Fto5o-5ea0sNMlW_75VgGJCv2AcJ', null);
}
$blockCnt = self::blockCount($fsize);
$sha1Buf = array();
if ($blockCnt <= 1) {
array_push($sha1Buf, 0x16);
$fdata = fread($fhandler, self::BLOCK_SIZE);
if ($err !== null) {
fclose($fhandler);
return array(null, $err);
}
list($sha1Code,) = self::calcSha1($fdata);
$sha1Buf = array_merge($sha1Buf, $sha1Code);
} else {
array_push($sha1Buf, 0x96);
$sha1BlockBuf = array();
for ($i = 0; $i < $blockCnt; $i++) {
$fdata = fread($fhandler, self::BLOCK_SIZE);
list($sha1Code, $err) = self::calcSha1($fdata);
if ($err !== null) {
fclose($fhandler);
return array(null, $err);
}
$sha1BlockBuf = array_merge($sha1BlockBuf, $sha1Code);
}
$tmpData = self::packArray('C*', $sha1BlockBuf);
list($sha1Final,) = self::calcSha1($tmpData);
$sha1Buf = array_merge($sha1Buf, $sha1Final);
}
$etag = self::base64_urlSafeEncode(self::packArray('C*', $sha1Buf));
return array($etag, null);
}
}
... ...
<?php
namespace App\Helper;
use App\Utils\HttpUtils;
use GuzzleHttp\Exception\GuzzleException;
/**
* Class FormGlobalsoApi
* @package App\Helper
* @author zbj
* @date 2023/5/17
*/
class FormGlobalsoApi
{
//接口地址
protected $url = 'https://form.globalso.com';
/**
* 设置询盘通知
* @author zbj
* @date 2023/5/17
*/
public function setInquiry($domain, $emails, $phones)
{
$api_url = $this->url . '/api/external-project/save/dc77a54480b184c4';
$params = [
'token' => md5($domain.$emails.$phones.date("Y-m-d")),
'domain' => $domain,
'email' => $emails,
'phone' => $phones,
];
try {
$res = HttpUtils::get($api_url, $params);
$res = Arr::s2a($res);
} catch (\Exception | GuzzleException $e) {
errorLog('设置询盘通知', $params, $e);
return false;
}
return $res;
}
/**
* 询盘列表
* @author zbj
* @date 2023/5/17
*/
public function getInquiryList($domain, $search = '', $page = 1, $page_size = 20)
{
$api_url = $this->url . '/api/external-interface/6a1bd159b1fd60af';
$params = [
'token' => md5($domain.$search.date("Y-m-d")),
'domain' => $domain,
'limit' => $page_size,
'page' => $page,
'source' => '1,3' //来源类型 新项目用1,3
];
if($search){
$params['name'] = $search;
}
try {
$res = HttpUtils::get($api_url, $params);
$res = Arr::s2a($res);
} catch (\Exception | GuzzleException $e) {
errorLog('询盘列表', $params, $e);
return false;
}
return $res;
}
/**
* 设置询盘信息已读
* @author zbj
* @date 2023/5/17
*/
public function saveInquiryRead($domain, $id)
{
$api_url = $this->url . '/api/external-interface/save/d1483a8e57cb485a';
$params = [
'token' => md5($domain.$id.date("Y-m-d")),
'domain' => $domain,
'id' => $id,
];
try {
$res = HttpUtils::get($api_url, $params);
$res = Arr::s2a($res);
} catch (\Exception | GuzzleException $e) {
errorLog('设置询盘信息已读', $params, $e);
return false;
}
return $res;
}
/**
* 删除询盘信息
* @author zbj
* @date 2023/5/17
*/
public function delInquiry($domain, $ids)
{
$api_url = $this->url . '/api/external-interface/del/c4b11cf6f1508489';
$ids = Arr::arrToSet($ids);
$params = [
'token' => md5($domain.$ids.date("Y-m-d")),
'domain' => $domain,
'id' => $ids,
];
try {
$res = HttpUtils::get($api_url, $params);
$res = Arr::s2a($res);
} catch (\Exception | GuzzleException $e) {
errorLog('删除询盘信息', $params, $e);
return false;
}
return $res;
}
}
... ...
<?php
namespace App\Helper;
use App\Utils\HttpUtils;
use GuzzleHttp\Exception\GuzzleException;
/**
* Class PageSpeed
* @package App\Helper
* @author zbj
* @date 2023/5/10
*/
class GoogleSpeedApi
{
protected $areas = [
[
"area" => "洛杉矶",
"numericValue" => 0,
],
[
"area" => "圣地亚哥",
"numericValue" => 0,
],
[
"area" => "伦敦",
"numericValue" => 0,
],
[
"area" => "西雅图",
"numericValue" => 0,
],
[
"area" => "吉隆坡",
"numericValue" => 0,
],
[
"area" => "雅加达",
"numericValue" => 0,
],
[
"area" => "孟买",
"numericValue" => 0,
],
[
"area" => "迪拜",
"numericValue" => 0,
],
[
"area" => "法兰克福",
"numericValue" => 0,
],
[
"area" => "新加坡",
"numericValue" => 0,
],
[
"area" => "悉尼",
"numericValue" => 0,
],
[
"area" => "东京",
"numericValue" => 0,
],
[
"area" => "硅谷",
"numericValue" => 0,
],
[
"area" => "弗吉尼亚",
"numericValue" => 0,
],
[
"area" => "香港",
"numericValue" => 0,
],
[
"area" => "圣保罗",
"numericValue" => 0,
],
[
"area" => "雅典",
"numericValue" => 0,
],
[
"area" => "巴黎",
"numericValue" => 0,
],
[
"area" => "罗马",
"numericValue" => 0,
],
[
"area" => "马德里",
"numericValue" => 0,
],
];
/**
* @param $url
* @return array|false
* @author zbj
* @date 2023/5/10
*/
function run($url)
{
try {
$params = [
'url' => $url
];
$res = HttpUtils::get('http://45.136.131.72/api.php', $params);
if ($res) {
$res = Arr::s2a($res);
$area_data = Arr::s2a($res['area_data']);
}
$numericValue = $area_data[0]['numericValue'] ?? rand(500, 1000);
foreach ($this->areas as &$area) {
$start = -$numericValue * 0.5;
$end = $numericValue * 0.5;
$numer = rand($start, $end);
$area["numericValue"] = ceil($numericValue - $numer);
}
return [
"url" => $url,
"area_data" => $this->areas,
"created_at" => date("Y-m-d H:i:s")
];
} catch (\Exception | GuzzleException $e) {
errorLog('测速失败', $params, $e);
return false;
}
}
}
... ...
<?php
namespace App\Helper;
use App\Utils\HttpUtils;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Cache;
/**
* Class QuanqiusouApi
* @package App\Helper
* @author zbj
* @date 2023/5/11
*/
class QuanqiusouApi
{
//接口地址
protected $url = 'http://api.quanqiusou.cn';
/**
* 所有站点收录页面数
* @author zbj
* @date 2023/5/11
*/
public function getSiteRes()
{
$key = 'quanqiusou_api_site_res_' . date('Y-m-d');
$res = Cache::get($key);
if (!$res) {
$api_url = $this->url . '/google-rank/echo_site_res.php';
try {
$res = HttpUtils::get($api_url, []);
if($res){
$res = Arr::s2a($res);
Cache::put($key, $res, 24 * 3600);
}
} catch (\Exception | GuzzleException $e) {
errorLog('获取站点收录页面数', [], $e);
return false;
}
}
return $res;
}
/**
* 指定站点收录页面数
* @param $api_no
* @return array|false|mixed
* @author zbj
* @date 2023/5/11
*/
public function getSiteResPer($api_no){
$key = 'quanqiusou_api_site_res_per_' . $api_no . '_' . date('Y-m-d');
$res = Cache::get($key);
if (!$res) {
$api_url = $this->url . '/google-rank/echo_site_res_per.php';
try {
$res = HttpUtils::get($api_url, ['apino' => $api_no]);
if($res){
$res = Arr::s2a($res);
Cache::put($key, $res, 24 * 3600);
}
} catch (\Exception | GuzzleException $e) {
errorLog('获取站点收录页面数', [], $e);
return false;
}
}
return $res;
}
/**
* 获取谷歌排名数据
* @param $api_no
* @param int $lang
* @param int $day
* @return array|false|mixed
* @author zbj
* @date 2023/5/11
*/
public function getGoogleRank($api_no, int $lang = 0, int $day = 7)
{
$key = "quanqiusou_api_rank_{$api_no}_{$lang}_{$day}_" . date('Y-m-d');
$res = Cache::get($key);
if (!$res) {
$param = [
'key' => '289c1fc81c89d79c04ed4fd72822948e',
'w' => $api_no,
'type' => $day
];
if ($lang) {
$param['lang'] = $lang;
}
$api_url = $this->url . '/api';
try {
$res = HttpUtils::get($api_url, $param);
if($res){
$res = Arr::s2a($res);
Cache::put($key, $res, 24 * 3600);
}
} catch (\Exception | GuzzleException $e) {
errorLog('获取谷歌排名数据失败', $api_no, $e);
return false;
}
}
return $res;
}
/**
* 获取每周谷歌排名数据
* @return array|false|mixed
* @author zbj
* @date 2023/5/11
*/
public function getGoogleRankWeek()
{
$key = "quanqiusou_api_week_data_" . date('Y-m-d');
$res = Cache::get($key);
if (!$res) {
$api_url = $this->url . '/google-rank/echo_week_data.php';
try {
$res = HttpUtils::get($api_url, []);
if($res){
$res = Arr::s2a($res);
Cache::put($key, $res, 24 * 3600);
}
} catch (\Exception | GuzzleException $e) {
errorLog('获取每周谷歌排名数据失败', [], $e);
return false;
}
}
return $res;
}
/**
* 获取历史排名统计数据
* @param $api_no
* @param string $lang
* @return array|false|int|mixed|null
* @author zbj
* @date 2023/5/15
*/
public function getHistoryCount($api_no, $lang = '')
{
$key = "quanqiusou_api_history_count_{$api_no}_{$lang}_" . date('Y-m-d');
$res = Cache::get($key);
if (!$res) {
$api_url = $this->url . '/google-rank/history_count.php';
$param = [
'apino' => $api_no,
];
if ($lang) {
$param['lang'] = $lang;
}
try {
$res = HttpUtils::get($api_url, $param);
if($res){
$res = Arr::s2a($res);
Cache::put($key, $res, 24 * 3600);
}
} catch (\Exception | GuzzleException $e) {
errorLog('获取历史排名统计数据失败', [], $e);
return false;
}
}
return $res;
}
/**
* 获取小语种项目
* @return array|false|int|mixed|null
* @author zbj
* @date 2023/5/15
*/
public function getLangList()
{
$key = "quanqiusou_api_lang_list_" . date('Y-m-d');
$res = Cache::get($key);
if (!$res) {
$api_url = $this->url . '/api/index/langlist';
$param = [
'key' => '289c1fc81c89d79c04ed4fd72822948e',
];
try {
$res = HttpUtils::get($api_url, $param);
if($res){
$res = Arr::s2a($res);
Cache::put($key, $res, 2 * 3600);
}
} catch (\Exception | GuzzleException $e) {
errorLog('获取小语种项目数据失败', [], $e);
return false;
}
}
return $res;
}
/**
* 获取项目小语种信息
* @return array|false|int|mixed|null
* @author zbj
* @date 2023/5/15
*/
public function getLangRankData($api_no)
{
$key = "quanqiusou_get_language_rank_data_{$api_no}_" . date('Y-m-d');
$res = Cache::get($key);
if (!$res) {
$api_url = $this->url . '/api/index/get_language_rank_data';
$param = [
'apino' => $api_no,
];
try {
$res = HttpUtils::get($api_url, $param);
if($res){
$res = Arr::s2a($res);
Cache::put($key, $res, 24 * 3600);
}
} catch (\Exception | GuzzleException $e) {
errorLog('获取项目小语种数据失败', [], $e);
return false;
}
}
return $res;
}
}
... ...
<?php
namespace App\Helper;
use App\Utils\HttpUtils;
use GuzzleHttp\Exception\GuzzleException;
/**
* Class SemrushApi
* @package App\Helper
* @author zbj
* @date 2023/5/9
*/
class SemrushApi
{
//接口地址
protected $url = 'https://api.semrush.com';
protected $key = '2927058317c47207e4a8c4cacf10acfd';
/**
* 反链概述
*/
function backlinks_overview($target,$target_type = "root_domain"){
if($target){
$url = $this->url."/analytics/v1/?";
$params = [
"type"=>"backlinks_overview",
"key"=>$this->key,
"target"=>$target,
"target_type"=>$target_type,
"export_columns"=>"ascore,total,domains_num,urls_num,ips_num,ipclassc_num,follows_num,nofollows_num,sponsored_num,ugc_num,texts_num,images_num,forms_num,frames_num"
];
try {
$res = HttpUtils::get($url, $params);
return $this->data($res)[0];
}catch (\Exception|GuzzleException $e){
errorLog('获取站点外链数据', $params, $e);
return false;
}
}
return [];
}
/**
* 引荐域名
*/
public function backlinks_refdomains($target,$target_type = "root_domain",$offset = 0){
if($target){
$url = $this->url."/analytics/v1/?";
$params = [
"type"=>"backlinks_refdomains",
"key"=>$this->key,
"target"=>$target,
"target_type"=>$target_type,
"export_columns"=>"domain_ascore,domain,backlinks_num,ip,country,first_seen,last_seen",
"display_limit"=>10,
"display_offset"=>$offset
];
try {
$res = HttpUtils::get($url, $params);
return $this->data($res);
}catch (\Exception|GuzzleException $e){
errorLog('获取站点外链数据', $params, $e);
return false;
}
}
return [];
}
/**
* 处理结果
* @param $res
* @return array
* @author zbj
* @date 2023/5/9
*/
protected function data($res){
$temp = explode("\n",$res);
$arr =array_map(function ($v){
return explode(";",$v);
}, $temp);
$data = [];
for ($i = 1; $i < count($arr) - 1; $i++) {
$tmp = [];
foreach($arr[0] as $k =>$v){
$tmp[trim($v)] = trim($arr[$i][$k]);
}
$data[] = $tmp;
}
return $data;
}
}
... ...