['DEF' => 'default', 'CT' => 'telecom', 'CU' => 'unicom', 'CM' => 'mobile', 'AB' => 'oversea'], 'dnspod' => ['DEF' => '0', 'CT' => '10=0', 'CU' => '10=1', 'CM' => '10=3', 'AB' => '3=0'], 'huawei' => ['DEF' => 'default_view', 'CT' => 'Dianxin', 'CU' => 'Liantong', 'CM' => 'Yidong', 'AB' => 'Abroad'], 'west' => ['DEF' => '', 'CT' => 'LTEL', 'CU' => 'LCNC', 'CM' => 'LMOB', 'AB' => 'LFOR'], 'dnsla' => ['DEF' => '', 'CT' => '84613316902921216', 'CU' => '84613316923892736', 'CM' => '84613316953252864', 'AB' => ''], 'huoshan' => ['DEF' => 'default', 'CT' => 'telecom', 'CU' => 'unicom', 'CM' => 'mobile', 'AB' => 'oversea'], 'baidu' => ['DEF' => 'default', 'CT' => 'ct', 'CU' => 'cnc', 'CM' => 'cmnet', 'AB' => ''], ]; private $ip_address = []; private $add_num = 0; private $change_num = 0; private $del_num = 0; public static function get_license($api, $key) { if ($api == 2) { throw new Exception('当前接口暂不支持'); } elseif ($api == 1) { $url = 'https://api.hostmonit.com/get_license?license='.$key; } else { $url = 'https://www.wetest.vip/api/cf2dns/get_license?license='.$key; } $response = (new Client())->get($url)->getBody()->getContents(); $arr = json_decode($response, true); if (isset($arr['code']) && $arr['code'] == 200 && isset($arr['count'])) { return $arr['count']; } elseif (isset($arr['info'])) { throw new Exception('获取剩余请求次数失败,'.$arr['info']); } else { throw new Exception('获取剩余请求次数失败'); } } public function get_ip_address($cdn_type = 1, $ip_type = 'v4') { $api = config_get('optimize_ip_api', 0); if ($api == 2) { $url = 'https://api.345673.xyz/get_data'; } elseif ($api == 1) { $url = 'https://api.hostmonit.com/get_optimization_ip'; } else { $url = 'https://www.wetest.vip/api/cf2dns/'; if ($cdn_type == 1) { $url .= 'get_cloudflare_ip'; } elseif ($cdn_type == 2) { $url .= 'get_cloudfront_ip'; } elseif ($cdn_type == 3) { $url .= 'get_gcore_ip'; } } $params = [ 'key' => config_get('optimize_ip_key', 'o1zrmHAF'), 'type' => $ip_type, ]; $response = (new Client())->post($url, ['json' => $params])->getBody()->getContents(); $arr = json_decode($response, true); if (isset($arr['code']) && $arr['code'] == 200) { return $arr['info']; } elseif (isset($arr['info'])) { throw new Exception('获取优选IP数据失败,'.$arr['info']); } elseif (isset($arr['msg'])) { throw new Exception('获取优选IP数据失败,'.$arr['msg']); } else { throw new Exception('获取优选IP数据失败,原因未知'); } } public function get_ip_address2($cdn_type = 1, $ip_type = 'v4') { $key = $cdn_type.'_'.$ip_type; if (!isset($this->ip_address[$key])) { $info = $this->get_ip_address($cdn_type, $ip_type); $res = []; if (isset($info['DEF'])) { $res['DEF'] = $info['DEF']; } if (isset($info['CT'])) { $res['CT'] = $info['CT']; } if (isset($info['CU'])) { $res['CU'] = $info['CU']; } if (isset($info['CM'])) { $res['CM'] = $info['CM']; } $this->ip_address[$key] = $res; } return $this->ip_address[$key]; } //批量执行优选任务 public function execute() { $list = Optimizeip::where('active', 1)->select(); echo '开始执行IP优选任务,共获取到'.count($list).'个待执行任务'."\n"; foreach ($list as $row) { try { $result = $this->execute_one($row); Optimizeip::where('id', $row['id'])->update(['status' => 1, 'errmsg' => null, 'updatetime' => date('Y-m-d H:i:s')]); echo '优选任务'.$row['id'].'执行成功:'.$result."\n"; } catch (Exception $e) { Optimizeip::where('id', $row['id'])->update(['status' => 2, 'errmsg' => $e->getMessage(), 'updatetime' => date('Y-m-d H:i:s')]); echo '优选任务'.$row['id'].'执行失败:'.$e->getMessage()."\n"; } } } //执行单个优选任务 public function execute_one($row) { $this->add_num = 0; $this->change_num = 0; $this->del_num = 0; $ip_types = explode(',', $row['ip_type']); foreach ($ip_types as $ip_type) { if (empty($ip_type)) { continue; } $drow = Domain::alias('A')->join('account B', 'A.aid = B.id')->where('A.id', $row['did'])->field('A.*,B.type,B.ak,B.sk,B.ext')->find(); if (!$drow) { throw new Exception('域名不存在(ID:'.$row['did'].')'); } if (!isset(self::$line_name[$drow['type']])) { throw new Exception('不支持的DNS服务商'); } $info = $this->get_ip_address2($row['cdn_type'], $ip_type); $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']); $domainRecords = $dns->getSubDomainRecords($row['rr'], 1, 100); if (!$domainRecords) { throw new Exception('获取记录列表失败,'.$dns->getError()); } if ($row['type'] == 1 && isset($info['DEF']) && !empty($info['DEF'])) { $row['type'] = 0; } foreach ($info as $line => $iplist) { if (empty($iplist)) { continue; } $get_ips = array_column($iplist, 'ip'); if ($drow['type'] == 'huawei') { sort($get_ips); $get_ips = [implode(',', $get_ips)]; $row['recordnum'] = 1; } if ($row['type'] == 1 && $line == 'CT') { $line = 'DEF'; } $line_name = self::$line_name[$drow['type']][$line]; $this->process_dns_line($dns, $row, $domainRecords['list'], $get_ips, $line_name, $ip_type); } } return '成功添加'.$this->add_num.'条记录,修改'.$this->change_num.'条记录,删除'.$this->del_num.'条记录'; } //处理单个线路的解析记录 private function process_dns_line($dns, $row, $record_list, $get_ips, $line_name, $ip_type) { $record_num = $row['recordnum']; $records = array_filter($record_list, function ($v) use ($line_name) { return $v['Line'] == $line_name; }); //删除CNAME记录 $cname_records = array_filter($records, function ($v) { return $v['Type'] == 'CNAME'; }); if (!empty($cname_records)) { foreach ($cname_records as $record) { $dns->deleteDomainRecord($record['RecordId']); } } //处理A/AAAA记录 $ip_records = array_filter($records, function ($v) use ($ip_type) { return $v['Type'] == ($ip_type == 'v6' ? 'AAAA' : 'A'); }); if (!empty($ip_records) && is_array($ip_records[array_key_first($ip_records)]['Value'])) { //处理华为云记录 foreach ($ip_records as &$ip_record) { sort($ip_record['Value']); $ip_record['Value'] = implode(',', $ip_record['Value']); } } $exist_ips = array_column($ip_records, 'Value'); $add_ips = array_diff($get_ips, $exist_ips); $del_ips = array_diff($exist_ips, $get_ips); $correct_ips = array_diff($exist_ips, $del_ips); $correct_count = count($correct_ips); if (!empty($del_ips)) { foreach ($ip_records as $record) { if (in_array($record['Value'], $del_ips)) { $add_ip = array_pop($add_ips); if ($add_ip) { $res = $dns->updateDomainRecord($record['RecordId'], $row['rr'], $ip_type == 'v6' ? 'AAAA' : 'A', $add_ip, $line_name, $row['ttl']); if (!$res) { throw new Exception('修改解析失败,'.$dns->getError()); } $this->change_num++; $correct_count++; } else { $res = $dns->deleteDomainRecord($record['RecordId']); if (!$res) { throw new Exception('删除解析失败,'.$dns->getError()); } $this->del_num++; } } } } if ($correct_count < $record_num && !empty($add_ips)) { foreach ($add_ips as $add_ip) { $res = $dns->addDomainRecord($row['rr'], $ip_type == 'v6' ? 'AAAA' : 'A', $add_ip, $line_name, $row['ttl']); if (!$res) { throw new Exception('添加解析失败,'.$dns->getError()); } $this->add_num++; $correct_count++; if ($correct_count >= $record_num) { break; } } } } }