#!/bin/bash
# 功能实现：根据指定的域名，查询对于应域名所在解析组的相关信息
# 依赖文件：dna/
# 存在问题：
#

# 自定义控制台颜色显示
c_br='\e[1;31m'     # bold red
c_bg='\e[1;32m'     # bold green
c_bc='\e[1;36m'     # bold cyan
c_by='\e[1;33m'     # bold yellow
c_bp='\e[1;35m'     # bold purple
c_bir='\e[1;3;31m'  # bold italic red
c_big='\e[1;3;32m'  # bold italic green
c_biy='\e[1;3;33m'  # bold italic yellow
c_bib='\e[1;3;34m'  # bold italic blue
c_bip='\e[1;3;35m'  # bold italic purple
c_bic='\e[1;3;36m'  # bold italic cyan
c_biw='\e[1;3;30m'  # bold italic gray
c_e='\e[0m'         # reset

# 使用说明
function usage {
  echo -e "${c_bib}Usage:                                                                        ${c_e}"
  echo -e "${c_bib}  map -d domain vip     # 从域名解析组中随机获取一个VIP                       ${c_e}"
  echo -e "${c_bib}  map -d domain rip     # 从域名解析组中随机获取一个RIP                       ${c_e}"
  echo -e "${c_bib}  map -d domain ip      # 验证一个IP是否属于域名解析组中的VIP或者RIP          ${c_e}"
  echo -e "${c_bib}  map -d domain label   # 验证一个节点中/英文标签名是否包含在域名解析组中     ${c_e}"
  echo -e "${c_bib}  map -d domain label   # 打印域名解析组中所有的节点信息                      ${c_e}"
  echo -e "${c_bib}  map -d domain cover   # 输出域名边缘解析组节点资源覆盖情况，可指定区域查询  ${c_e}"
  echo -e "${c_bib}  map -d domain parent  # 输出域名父解析组节点资源覆盖情况，可指定区域查询    ${c_e}\n"
  echo -e "${c_bic}[MAP-100] 该脚本工具会根据指定的域名，查询对于应域名所在解析组的相关信息，其中vip/rip/pool/cover/parent均是字符串参数，domain/ip是实际要输入真实值的参数，label既可以是字符串参数，也可以是实际节点中/英文标签名称。${c_e}\n"
  exit 100
}

function onCtrlC () {
  # while capture Ctrl+C, kill all background processes silently and exit
  exec 3>&2          # 3 is now a copy of 2
  exec 2> /dev/null  # 2 now points to /dev/null
  sleep 1            # sleep to wait for process to die
  exec 2>&3          # restore stderr to saved
  exec 3>&-          # close saved version
  echo
  echo -e "${c_bir}[MAP-101] Ctrl+C is captured, exiting...\n${c_e}"
  exit 101
}

# 随机获取域名对应解析组的一个VIP
function random_vip() {
    # 其实支持的不仅如下，只要输入正确，其他网络运营商也是可以查询的
    echo -ne "${c_bg}请输入ISP类型--【ct|cu|cm|bgp|ctbgp|cubgp|cmbgp】：${c_e}"
    read -t 60 isp
    [[ $? -ne 0 ]] && { echo -e "${c_br}[MAP-102] 60s内无任何输入，退出...${c_e}\n"; exit 102; }
    # do a check to see if isp is correct or not
    [[ $isp == '' ]] && isp='ct'
    # 从解析组VIP列过滤以运营商标识开头的节点和VIP
    ip_list=`cat map.log | awk '{print $4, $5}' | grep "^${isp}_" | awk '{print $2}' | sort | uniq`
    [[ $ip_list == '' ]] && { echo -e "${c_br}[MAP-103] 在解析组$map中，没有找到$isp的网络运营商，退出...${c_e}"; exit 103; }
    # 匹配v6和v4的子集
    v6_list=`echo $ip_list | grep -Eo "[0-9a-fA-F:]{11,39}"`
    v4_list=`echo $ip_list | grep -Eo "([0-9]{1,3}\.){3}[0-9]{1,3}"`
    # 计算分别有多少个
    num_v6=`echo $v6_list | awk '{print NF}'`
    num_v4=`echo $v4_list | awk '{print NF}'`
    # 获取随机的IP，注意用$RANDOM取模之后，结果有可能是0，最大值不超过总数，所以需要 +1
    [[ num_v6 -ne 0 ]] && rand6=$(( $RANDOM % $num_v6 )) && vip_v6=`echo $v6_list | awk -v v6=$rand6 '{print $(v6+1)}'`
    [[ num_v4 -ne 0 ]] && rand4=$(( $RANDOM % $num_v4 )) && vip_v4=`echo $v4_list | awk -v v4=$rand4 '{print $(v4+1)}'`
    echo "vip_v6: $vip_v6"
    echo "vip_v4: $vip_v4"
    echo -e "${c_bip}MAP: $map\n${c_e}"
}


# 随机获取域名对应解析组的一个RIP
function random_rip() {
    # 其实支持的不仅如下，只要输入正确，其他网络运营商也是可以查询的
    echo -ne "${c_bg}请输入ISP类型--【ct|cu|cm|bgp|ctbgp|cubgp|cmbgp】：${c_e}"
    read -t 60 isp
    [[ $? -ne 0 ]] && { echo -e "${c_br}[MAP-104] 60s内无任何输入，退出...${c_e}\n"; exit 104; }
    # do a check to see if isp is correct or not
    [[ $isp == '' ]] && isp='ct'
    # 从解析组VIP列过滤以运营商标识开头的节点和VIP
    ip_list=`cat map.log | awk '{print $4, $5}' | grep "^${isp}_" | awk '{print $2}' | sort | uniq`
    [[ $ip_list == '' ]] && { echo -e "${c_br}[MAP-106] 在解析组$map中，没有找到$isp的网络运营商，退出...${c_e}"; exit 105; }
    # 匹配v6和v4的子集
    v6_list=`echo $ip_list | grep -Eo "[0-9a-fA-F:]{11,39}"`
    v4_list=`echo $ip_list | grep -Eo "([0-9]{1,3}\.){3}[0-9]{1,3}"`
    # 计算分别有多少个
    num_v6=`echo $v6_list | awk '{print NF}'`
    num_v4=`echo $v4_list | awk '{print NF}'`
    # 获取随机的IP，注意用$RANDOM取模之后，结果有可能是0，最大值不超过总数，所以需要 +1
    [[ num_v6 -ne 0 ]] && rand6=$(( $RANDOM % $num_v6 )) && vip_v6=`echo $v6_list | awk -v v6=$rand6 '{print $(v6+1)}'`
    [[ num_v4 -ne 0 ]] && rand4=$(( $RANDOM % $num_v4 )) && vip_v4=`echo $v4_list | awk -v v4=$rand4 '{print $(v4+1)}'`
    # 拿到VPI之后，使用`ips`获取RIP列表
    [[ num_v6 -ne 0 ]] && v6_list=`ips $vip_v6 | sed -n '/RIP/, /VIP/ p' | grep -Eo '([0-9]{1,3}.){3}[0-9]{1,3}'`
    [[ num_v4 -ne 0 ]] && v4_list=`ips $vip_v4 | sed -n '/RIP/, /VIP/ p' | grep -Eo '([0-9]{1,3}.){3}[0-9]{1,3}'`
    # 计算分别有多少个
    num_v6=`echo $v6_list | awk '{print NF}'`
    num_v4=`echo $v4_list | awk '{print NF}'`
    # 获取随机的IP，注意用$RANDOM取模之后，结果有可能是0，最大值不超过总数，所以需要 +1
    [[ num_v6 -ne 0 ]] && rand6=$(( $RANDOM % $num_v6 )) && rip_v6=`echo $v6_list | awk -v v6=$rand6 '{print $(v6+1)}'`
    [[ num_v4 -ne 0 ]] && rand4=$(( $RANDOM % $num_v4 )) && rip_v4=`echo $v4_list | awk -v v4=$rand4 '{print $(v4+1)}'`

    echo "rip_v6: $rip_v6"
    echo "rip_v4: $rip_v4"
    echo -e "${c_bip}MAP: $map\n${c_e}"
}


# 判断一个IP是否归属域名的解析组，可以是VIP，也可以是RIP
function ip_inmap() {
    # 使用`ips`判断IP是否在天翼平台
    ips $item > ips.log 2>&1
    [[ $? -ne 0 ]] && { cat ips.log; echo -e "${c_br}[MAP-106]${c_e}"; exit 106; }
    # 判断IP是否是RIP
    cat $data/ip.group | awk '{print $1}' | grep -wq $item
    is_rip=$?
    # 如果是RIP
    if [[ $is_rip -eq 0 ]]; then
        # 获取对应RIP的英文节点标签名，并判断该节点是否在域名的解析组中
        label=`cat ips.log | grep -Eo "(ct|cu|cm|bgp|ctbgp|cmbgp|cubgp|as|eu|sa|na|cbn|cern)_[a-z]{2,3}_[a-z]{2,20}[0-9]{1,2}_(c|e|m|n)[0-9]{0,2}" | head -n 1`
        cat map.log | awk '{print $4}' | sort | uniq | grep -wq $label
        if [[ $? -eq 0 ]]; then
          echo -e "${c_big}$item是域名$domain对应解析组$map中的IP，并且是一个RIP。\n${c_e}"
        else
          echo -e "${c_bir}[MAP-107] $item${c_biy}不是${c_bir}域名$domain对应解析组中的IP。\n${c_e}"
          exit 107
        fi
    # 如果不是RIP，那就是VIP
    else
        # 直接判断该IP是否在域名的解析组
        cat map.log | awk '{print $5}' | sort | uniq | grep -wq $item
        if [[ $? -eq 0 ]]; then
          echo -e "${c_big}$item是域名$domain对应解析组$map中的IP，并且是一个VIP。\n${c_e}"
        else
          echo -e "${c_bir}[MAP-108] $item${c_biy}不是${c_bir}域名$domain对应解析组中的IP。\n${c_e}"
          exit 108
        fi
    fi
}

# 判断一个标签是否在域名的解析组中
function label_inmap() {
    # 输出改解析组所有的节点中英文对应标签信息
    cat map.log | awk '{print $14, $4}' | sed '1d' | sort | uniq | awk '{if(NR%3==0) print " | "$0" | "; else printf "%s", " | "$0;} END{print ""}' | column -t
    # 查询节点中英文标签名称是否在域名的解析组中，在的话并输出相应信息
    cat map.log | awk '{print $14, $4}' | sort | uniq | grep -wq $item
    if [[ $? -eq 0 ]]; then
      node=`cat map.log | awk '{print $14, $4}' | sort | uniq | grep -w $item`
      echo -e "${c_big}$node${c_by} 是域名 $domain 对应解析组 $map 中的节点，如上是该解析组所有节点列表汇总，可参考。\n${c_e}"
    else
      echo -e "${c_bir}[MAP-109] $item${c_biy} 不是${c_bir}域名 $domain 对应解析组 $map 中的节点，如上是该解析组所有节点列表汇总，可参考。\n${c_e}"
      exit 109
    fi
}


# 打印域名对应解析组所有节点信息
function labels_inmap() {
    cat map.log | awk '{print $14, $4}' | sed '1d' | sort | uniq | awk '{if(NR%3==0) print " | "$0" | "; else printf "%s", " | "$0;} END{print ""}' | column -t
    echo -e "${c_big}如上是域名 $domain 对应解析组 $map 所有节点列表汇总，可参考。\n${c_e}"
}

# 输出域名对应解析组的覆盖情况，可指定地区
function cover() {
    # 宽度提示
    width=`tput cols`
    if [[ $width -lt 170 ]]; then
        echo -e "${c_biy}因该选项输出的每行数据比较多，需要终端宽度大于170，当前终端宽度为$width，输出的界面会不整齐，是否继续(Y/n)：${c_e}"
        read -t 60 YON
        [[ $? -ne 0 ]] && { echo -e "${c_br}[MAP-110] 60s内无任何输入，退出...${c_e}\n"; exit 110; }
        if [[ $YON != '' && $YON != 'y' && $YON != 'Y' && $YON != 'Yes' && $YON != 'yes' && $YON != 'YES' ]]; then
            echo -e "${c_br}[MAP-111] 请调整终端宽度之后，重新运行，退出...${c_e}\n"
            exit 111
        fi
    fi

    # 将需要保留的的字段过滤出来
    cat map.log | sed '1d' | awk '{print $1, $2, $3, $4, $5, $14, $16, $22, $16-$22, $23, $24}' | sort -k 2 > res.map
    echo -e "${c_bib}1. 省份维度：31个省市自治区 + 电信|移动|联通，例如-内蒙古电信${c_e}"
    echo -e "${c_bib}2. 大区维度：东北|华北|华东|华南|华中|西北|西南 + 电信|移动|联通|长宽|铁通|广电，例如-东北移动${c_e}"
    echo -e "${c_bib}3. 全国维度：中国 + 电信|移动|联通|长宽|铁通|广电|其他/香港/澳门/台湾/教育网，例如-中国移动${c_e}"
    echo -e "${c_bib}4. 国际维度：日本/韩国/蒙古国/北朝鲜/澳洲/欧洲/非洲/北美洲/南美洲/中亚/西亚/南亚/东南亚/亚洲其他等${c_e}"
    echo -e "${c_bib}5. 其他维度：全球/其他/其他广电/其他电信/其他移动/其他联通/其他铁通/其他长宽${c_e}"
    echo -ne "${c_bg}请按照如上规则，输入查询条件：${c_e}\n"
    read -t 60 query
    [[ $? -ne 0 ]] && { echo -e "${c_br}[MAP-112] 60s内无任何输入，退出...${c_e}\n"; exit 112; }
    # 无任何输入，则默认打印所有资源
    if [[ ${query} == '' ]]; then
        python3 /usr/local/script/fanmf11/get_infos.py --format-global res.map
        # python3 /home/fanmf11/fanmf11/get_infos.py --format-global res.map
    # 否则打印指定地区的资源覆盖情况
    else
        cat $data/area | grep $query| awk '{print $1}' > view
        python3 /usr/local/script/fanmf11/get_infos.py --format-partial $query view res.map $domain $map
        # python3 /home/fanmf11/fanmf11/get_infos.py --format-partial $query view res.map $domain $map
    fi
}

# 输出域名对应父解析组的覆盖情况，可指定地区
function parent() {
    # 宽度提示
    width=`tput cols`
    if [[ $width -lt 170 ]]; then
        echo -e "${c_biy}因该选项输出的每行数据比较多，需要终端宽度大于170，当前终端宽度为$width，输出的界面会不整齐，是否继续(Y/n)：${c_e}"
        read -t 60 YON
        [[ $? -ne 0 ]] && { echo -e "${c_br}[MAP-113] 60s内无任何输入，退出...${c_e}\n"; exit 113; }
        if [[ $YON != '' && $YON != 'y' && $YON != 'Y' && $YON != 'Yes' && $YON != 'yes' && $YON != 'YES' ]]; then
            echo -e "${c_br}[MAP-114] 请调整终端宽度之后，重新运行，退出...${c_e}\n"
            exit 114
        fi
    fi

    # 获取域名的父解析组
    # python3 /usr/local/script/fanmf11/get_infos.py --domain_config_accid map_info.log $domain
    infos --parent $domain $TS
    cat cmap && echo -e "${c_bg}请选择要查看的父方案序号(e.g. 1, 2, 3...)：${c_e}"
    read -t 60 index
    [[ $? -ne 0 ]] && { echo -e "${c_br}[MAP-115] 60s内无任何输入，退出...${c_e}\n"; exit 115; }
    cat cmap | grep -Eq "^$index\."
    [[ $? -ne 0 ]] && { echo -e "${c_br}[MAp-116] 请输入正确的序号，退出...${c_e}\n"; exit 116; }
    cmap=`cat cmap | grep -E "^$index\." | awk '{print $2}'`
    getlastcover $cmap > cmap.log 2>&1


    # 将需要保留的的字段过滤出来
    cat cmap.log | sed '1d' | awk '{print $1, $2, $3, $4, $5, $14, $16, $22, $16-$22, $23, $24}' | sort -k 2 > res.map
    echo -e "${c_bib}1. 省份维度：31个省市自治区 + 电信|移动|联通，例如-内蒙古电信${c_e}"
    echo -e "${c_bib}2. 大区维度：东北|华北|华东|华南|华中|西北|西南 + 电信|移动|联通|长宽|铁通|广电，例如-东北移动${c_e}"
    echo -e "${c_bib}3. 全国维度：中国 + 电信|移动|联通|长宽|铁通|广电|其他/香港/澳门/台湾/教育网，例如-中国移动${c_e}"
    echo -e "${c_bib}4. 国际维度：日本/韩国/蒙古国/北朝鲜/澳洲/欧洲/非洲/北美洲/南美洲/中亚/西亚/南亚/东南亚/亚洲其他等${c_e}"
    echo -e "${c_bib}5. 其他维度：全球/其他/其他广电/其他电信/其他移动/其他联通/其他铁通/其他长宽${c_e}"
    echo -ne "${c_bg}请按照如上规则，输入查询条件：${c_e}\n"
    read -t 60 query
    [[ $? -ne 0 ]] && { echo -e "${c_br}[MAP-117] 60s内无任何输入，退出...${c_e}\n"; exit 117; }
    # 无任何输入，则默认打印所有资源
    if [[ ${query} == '' ]]; then
        python3 /usr/local/script/fanmf11/get_infos.py --format-global res.map
        # python3 /home/fanmf11/fanmf11/get_infos.py --format-global res.map
    # 否则打印指定地区的资源覆盖情况
    else
        cat $data/area | grep $query| awk '{print $1}' > view
        python3 /usr/local/script/fanmf11/get_infos.py --format-partial $query view res.map $domain $map
        # python3 /home/fanmf11/fanmf11/get_infos.py --format-partial $query view res.map $domain $map
    fi
}

function logfile() {
    if [[ -d $trash ]]; then
        echo -e "${c_br}[MAP-118]对于同一个用户，同一时间只能运行一个实例，请重新运行...${c_e}"
        exit 118
    else
        mkdir -p $trash
        cd $trash && cd ..
        docs=`ls`
        for doc in $docs; do
            [[ -f $doc ]] && rm -rf $doc
        done
        folders=`ls -t`
        while [[ `echo $folders | awk '{print NF}'` -gt 29 ]]; do
            folder=`ls -t | tail -1`
            rm -rf $folder
            folders=`ls -t`
        done
        cd $trash && touch map
    fi
}

# --------------------------------------------------------------------------------
# set a trap for Ctrl+C
trap 'onCtrlC' INT

# --------------------------------------------------------------------------------
# 初始化设定
stty erase '^H'                                     # allow backspace
data='/usr/local/script/fanmf11/data'               # set data directory path
toolbox='/usr/local/script/fanmf11/'                # set toobbox directory path
map=''
accid=''
TS=`date +%s%N`                                     # document the start time of the script
host=`whoami`                                       # who use this script
trash="/usr/local/script/fanmf11/trash/$host/$TS"   # set trash directory path

# --------------------------------------------------------------------------------
# 入参正确性检测
let NumOP=$#                                    # number of parameter
OP="prefix "$@                                  # do a prefix cause '-' char may damage echo command
dash_d=`echo $OP | awk '{print $2}'`            # get first param -d
domain=`echo $OP | awk '{print $3}'`            # get second param domain
item=`echo $OP | awk '{print $4}'`              # get third param item, can be vip, rip, testip, pool, cover etc.
[[ $NumOP -ne 3 || $dash_d != '-d' ]] && usage || logfile

# --------------------------------------------------------------------------------
# 检查域名是否在平台注册
res=`cat $data/domain.list | grep -w "$domain"`
[[ $res == '' ]] && { echo -e "${c_br}[MAp-119] 该域名未在天翼平台配置，一个小时内新增的域名无法查询，退出...${c_e}"; exit 119; }

# --------------------------------------------------------------------------------
# 获取域名解析组信息
infos --map $domain $TS
[[ $? -eq 205 || $? -eq 231 ]] && { echo -e "${c_br}[MAP-120] exiting...${c_e}"; exit 120; }
# cd $trash && map=`cat map.log` && getlastcover $map > map.log
cd $trash
if [[ `cat map.log | wc -l` -eq 1 ]]; then
    map=`cat map.log`
else
    maps=`cat map.log | sort | uniq`
    count=1 && > remap.log
    for map in $maps; do
        echo $count": "$map | tee -a remap.log
        let count=count+1
    done
    echo -ne "${c_bg}存在分区域解析，需确定解析组名称(默认是1)：${c_e}\n"
    read -t 60 imap
    [[ $? -ne 0 ]] && { echo -e "${c_br}[MAP-121] 60s内无任何输入，退出...${c_e}\n"; exit 121; }
    # do a check to see if isp is correct or not
    [[ $imap == '' ]] && let imap=1
    map=`cat remap.log | awk -F ':' -v imap=$imap '$1==imap {print $2}'`
    [[ $map == '' ]] && { echo -e "${c_br}[MAP-122] 请输入正确的序号，退出...${c_e}"; exit 122; }
fi
    
getlastcover $map > map.log
cat map.log | grep -q 'can not find sys_id'
[[ $? -eq 0 ]] && { echo -e "${c_br}[MAP-123] 该解析组未在平台配置，退出...${c_e}"; exit 123; }



# --------------------------------------------------------------------------------
# 随机获取VIP
if [[ $item == 'vip' ]]; then
    random_vip
elif [[ $item == 'rip' ]]; then
    random_rip
elif [[ $item =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ || $item =~ ^[0-9a-fA-F:]{11,39}$ ]]; then
    ip_inmap
elif [[ $item =~ ^(ct|cu|cm|bgp|ctbgp|cmbgp|cubgp|as|eu|sa|na|cbn|cern)_[a-z]{2,3}_[a-z]{2,20}[0-9]{1,2}_(c|dns|e|lvs|m|mysql|n|prets|pretw|redis|testts|ts|tw|uatts1)[0-9]{0,2}$ ]]; then
    label_inmap
elif [[ $item == 'label' ]]; then
    labels_inmap
elif [[ $item == 'cover' ]]; then
    cover
elif [[ $item == 'parent' ]]; then
    parent
# 兜底是中文节点名的查询
else
    label_inmap
fi


