#!/bin/sh
# Lucky 安装管理脚本 - 读取版本号和子目录
# 作者: 古大羊
# 日期: 2025-02-17

echo='echo -e' && [ -n "$(echo -e | grep e)" ] && echo=echo

luckPathSuff='lucky.daji'
download_base_url=$1 # 下载链接前缀（由第一个启动参数提供）
version=""
subdir=""
cpucore=""

# URL 解码函数
decode_url() {
    echo "$1" | sed 's/%/\\x/g' | while read -r line; do printf "%b\n" "$line"; done
}

# dir_avail 查询路径可用空间
dir_avail() {
    df -h $1 | awk '{ for(i=1;i<=NF;i++){ if(NR==1){ arr[i]=$i; }else{ arr[i]=arr[i]" "$i; } } } END{ for(i=1;i<=NF;i++){ print arr[i]; } }' | grep Ava | awk '{print $2}'
}

webget() {
    #参数【$1】代表下载目录，【$2】代表在线地址
    #参数【$3】代表输出显示，【$4】不启用重定向
    if curl --version >/dev/null 2>&1; then
        [ "$3" = "echooff" ] && progress='-s' || progress='-#'
        [ -z "$4" ] && redirect='-L' || redirect=''
        result=$(curl -w %{http_code} --connect-timeout 5 $progress $redirect -ko $1 $2)
        [ -n "$(echo $result | grep -e ^2)" ] && result="200"
    else
        if wget --version >/dev/null 2>&1; then
            [ "$3" = "echooff" ] && progress='-q' || progress='-q --show-progress'
            [ "$4" = "rediroff" ] && redirect='--max-redirect=0' || redirect=''
            certificate='--no-check-certificate'
            timeout='--timeout=3'
        fi
        [ "$3" = "echoon" ] && progress=''
        [ "$3" = "echooff" ] && progress='-q'
        wget $progress $redirect $certificate $timeout -O $1 $2
        [ $? -eq 0 ] && result="200"
    fi
}

getLinuxSysType() {
    [ -f "/etc/storage/started_script.sh" ] && systype=Padavan && initdir='/etc/storage/started_script.sh'
    [ -d "/jffs" ] && systype="asusrouter" && {
        [ -f "/jffs/.asusrouter" ] && initdir='/jffs/.asusrouter'
        [ -d "/jffs/scripts" ] && initdir='/jffs/scripts/init-start'
        [ -z "$initdir" ] && initdir='/jffs/scripts/init-start' && mkdir -p '/jffs/scripts'
    }
    [ -f "/data/etc/crontabs/root" -a "$(dir_avail /etc)" = 0 ] && systype=mi_snapshot

}

installStartDaemon() {
    echo "设为保守模式启动"
    type nohup >/dev/null 2>&1 && nohup=nohup
    $nohup $luckydir/lucky -c "$luckydir/lucky.conf" >/dev/null 2>&1 &
    cronset '#lucky保守模式守护进程' "*/1 * * * * test -z \"\$(pidof lucky)\" && $luckydir/lucky -c $luckydir/lucky.conf & #lucky保守模式守护进程"
}

installSetInit() {
    #判断系统类型写入不同的启动文件
    if [ -f /etc/rc.common ]; then
        #设为init.d方式启动
        echo "设为init.d方式启动"
        cp -f $luckydir/scripts/luckyservice /etc/init.d/$luckPathSuff
        chmod 755 /etc/init.d/$luckPathSuff
        /etc/init.d/$luckPathSuff enable
        /etc/init.d/$luckPathSuff start
    else
        [ -w /etc/systemd/system ] && sysdir=/etc/systemd/system
        [ -w /usr/lib/systemd/system ] && sysdir=/usr/lib/systemd/system
        if [ -n "$sysdir" ]; then

            #设为systemd方式启动
            echo "设为systemd方式启动"
            echo "sysdir:"$sysdir
            mv $luckydir/scripts/lucky.service $sysdir/$luckPathSuff.service
            sed -i "s%/etc/lucky%$luckydir%g" $sysdir/$luckPathSuff.service
            chmod 000 $sysdir/$luckPathSuff.service
            systemctl daemon-reload
            if [ ! $? = 0 ]; then
                echo "systemctl daemon-reload 出错， 转为保守模式..."
                installStartDaemon
            else
                systemctl enable $luckPathSuff.service
                systemctl start $luckPathSuff.service
            fi
        else
            #设为保守模式启动
            installStartDaemon
        fi
    fi

    #华硕/Padavan额外设置,开机启动
    [ -n "$initdir" ] && {
        echo "华硕/Padavan开机启动额外设置"$initdir
        sed -i '/Lucky启动/'d $initdir >/dev/null 2>&1
        if [ ! -e $initdir ]; then
            touch $initdir
            echo "#!/bin/sh" >>$initdir
        fi
        sed -i '/Lucky启动/'d $initdir 2>/dev/null
        echo "$luckydir/lucky -c $luckydir/lucky.conf >/dev/null& #Lucky启动脚本" >>$initdir
        chmod +x $initdir

    }
    #小米镜像化OpenWrt额外设置
    if [ "$systype" = "mi_snapshot" ]; then
        echo '执行小米镜像化OpenWrt额外设置'
        # 替换 misnap_init.sh 里的默认路径
        sed -i "s|luckydir=/data/lucky.daji|luckydir=$luckydir|g" "$luckydir/scripts/misnap_init.sh"
        chmod 755 $luckydir/scripts/misnap_init.sh
        uci set firewall.Lucky=include
        uci set firewall.Lucky.type='script'
        uci set firewall.Lucky.path="$luckydir/scripts/misnap_init.sh"
        uci set firewall.Lucky.enabled='1'
        uci commit firewall
    fi

}

installSetProfile() {
    [ -w /opt/etc/profile ] && profile=/opt/etc/profile
    [ -w /jffs/configs/profile.add ] && profile=/jffs/configs/profile.add
    [ -w ~/.bashrc ] && profile=~/.bashrc
    [ -w /etc/profile ] && profile=/etc/profile
    if [ -n "$profile" ]; then
        sed -i '/alias lucky=*/'d $profile
        echo "alias lucky=\"$luckydir/lucky\"" >>$profile #设置快捷命令环境变量
        sed -i '/export luckydir=*/'d $profile
        echo "export luckydir=\"$luckydir\"" >>$profile #设置快捷命令环境变量
    else
        echo 无法写入环境变量！请检查安装权限！
        exit 1
    fi
    echo 'Profile:'$profile
}

checkRoot() {
    #检查root权限
    if [ "$USER" != "root" -a -z "$systype" ]; then
        echo 当前用户:$USER
        $echo "\033[31m请尽量使用root用户（不要直接使用sudo命令！）执行安装!\033[0m"
        echo -----------------------------------------------
        read -r -p "仍要安装？可能会产生未知错误！(1/0) > " res
        [ "$res" != "1" ] && echo "Lukcy 安装脚本中止运行" && exit 1
    fi

}

croncmd() {
    if [ -n "$(crontab -h 2>&1 | grep '\-l')" ]; then
        crontab $1
    else
        crondir="$(crond -h 2>&1 | grep -oE 'Default:.*' | awk -F ":" '{print $2}')"
        [ ! -w "$crondir" ] && crondir="/etc/storage/cron/crontabs"
        [ ! -w "$crondir" ] && crondir="/var/spool/cron/crontabs"
        [ ! -w "$crondir" ] && crondir="/var/spool/cron"
        [ ! -w "$crondir" ] && echo "你的设备不支持定时任务配置"
        [ "$1" = "-l" ] && cat $crondir/$USER 2>/dev/null
        [ -f "$1" ] && cat $1 >$crondir/$USER
    fi
}

cronset() {
    # 参数1代表要移除的关键字,参数2代表要添加的任务语句
    tmpcron=/tmp/cron_$USER
    croncmd -l >$tmpcron
    sed -i "/$1/d" $tmpcron
    sed -i '/^$/d' $tmpcron
    echo "$2" >>$tmpcron
    croncmd $tmpcron
    rm -f $tmpcron
}

# 获取可用的 Lucky 版本号
get_versions() {
    echo "正在获取可用的 Lucky 版本列表..."
    if curl --version >/dev/null 2>&1; then
        versions=$(curl -s "$download_base_url/" | sed -n 's/.*href="\.\///p' | sed -E 's/\/.*//g' | grep '^v' | sort -u)
    elif wget --version >/dev/null 2>&1; then
        versions=$(wget -qO- "$download_base_url/" | sed -n 's/.*href="\.\///p' | sed -E 's/\/.*//g' | grep '^v' | sort -u)
    else
        echo "无法获取版本列表，请检查下载地址是否正确！"
        exit 1
    fi

    if [ -z "$versions" ]; then
        echo "未能获取可用的版本，请检查下载地址是否正确！"
        exit 1
    fi

    echo "-----------------------------------------------"
    echo "当前可下载安装的 Lucky 版本："
    echo "$versions" | awk '{print NR" "$0}'
    echo "-----------------------------------------------"
}

# 选择 Lucky 版本
select_version() {
    get_versions
    read -p "请输入对应的版本号编号 > " num
    version=$(echo "$versions" | awk "NR==$num")
    if [ -z "$version" ]; then
        echo -e "\033[31m输入错误，请重新选择！\033[0m"
        select_version
    fi
}

getcpucore() {
    cputype=$(uname -ms | tr ' ' '_' | tr '[A-Z]' '[a-z]')
    [ -n "$(echo $cputype | grep -E "linux.*armv.*")" ] && cpucore="armv5"
    [ -n "$(echo $cputype | grep -E "linux.*armv7.*")" ] && [ -n "$(cat /proc/cpuinfo | grep vfp)" ] && [ ! -d /jffs/clash ] && cpucore="armv7"
    [ -n "$(echo $cputype | grep -E "linux.*aarch64.*|linux.*armv8.*")" ] && cpucore="arm64"
    [ -n "$(echo $cputype | grep -E "linux.*86.*")" ] && cpucore="i386"
    [ -n "$(echo $cputype | grep -E "linux.*86_64.*")" ] && cpucore="x86_64"
    if [ -n "$(echo $cputype | grep -E "linux.*mips.*")" ]; then
        mipstype=$(echo -n I | hexdump -o 2>/dev/null | awk '{ print substr($2,6,1); exit}') #通过判断大小端判断mips或mipsle
        [ "$mipstype" = "0" ] && cpucore="mips_softfloat" || cpucore="mipsle_softfloat"
    fi
}

# 获取选定版本的子目录
get_subdirs() {
    echo "正在获取 $version 版本的可选子目录..."
    echo "万吉(全能)：包含所有模块，全功能版本"
    echo "Lucky(适中)：比万吉少FileBrowser模块、CorazaWAF模块以及不支持GRPC反向代理(>2.14.1)"
    if curl --version >/dev/null 2>&1; then
        subdirs=$(curl -s "$download_base_url/$version/" | sed -n 's/.*href="\.\///p' | sed -E 's/\/.*//g' | grep '^[0-9].*_' | sort -u | grep -v '^$')
    elif wget --version >/dev/null 2>&1; then
        subdirs=$(wget -qO- "$download_base_url/$version/" | sed -n 's/.*href="\.\///p' | sed -E 's/\/.*//g' | grep '^[0-9].*_' | sort -u | grep -v '^$')
    else
        echo "无法获取子目录列表，请检查下载地址是否正确！"
        exit 1
    fi

    if [ -z "$subdirs" ]; then
        echo "未能获取可用的子目录，请检查下载地址是否正确！"
        exit 1
    fi

    # 对获取到的子目录进行 URL 解码
    decoded_subdirs=$(decode_url "$subdirs")

    echo "-----------------------------------------------"
    echo "可用的子版本："
    echo "$decoded_subdirs" | grep -v '^$' | awk '{print NR" "$0}'
    echo "-----------------------------------------------"

    # 更新 subdirs 变量
    subdirs=$(echo "$decoded_subdirs" | grep -v '^$')
}

# 选择子目录
select_subdir() {
    get_subdirs
    read -p "请输入对应的子目录编号 > " num
    subdir=$(echo "$subdirs" | awk "NR==$num")
    if [ -z "$subdir" ]; then
        echo -e "\033[31m输入错误，请重新选择！\033[0m"
        select_subdir
    fi
}

checkdir() {
    if [ -n "$systype" ]; then
        [ "$systype" = "Padavan" ] && dir=/etc/storage
        [ "$systype" = "asusrouter" ] && dir=/jffs
        [ "$systype" = "mi_snapshot" ] && dir=/data
        echo "当前处于路由器系统环境:"+$systype
    fi
}

setdir() {
echo -----------------------------------------------
	$echo "\033[33m安装lucky至少需要预留约10MB的磁盘空间\033[0m"	
	$echo " 1 在\033[32m/etc\033[0m 目录下安装(适合root用户)"
	$echo " 2 在\033[32m/usr/share\033[0m目录下安装(适合Linux设备)"
	$echo " 3 在\033[32m当前用户目录\033[0m下安装(适合非root用户)"
	$echo " 4 在\033[32m/data\033[0m目录(小米官方路由系统)"
	$echo " 5 在\033[32m/data/userdisk \033[0m目录(小米官方路由系统.万兆)"
	$echo " 6 在\033[32m/jffs\033[0m目录(华硕/梅林)"
	$echo " 7 在\033[32m/etc/storage目录\033[0m(Padavan)"
	$echo " 8 手动设置安装目录"

	if [ -n "$dir" ];then
	 $echo " 5 在\033[32m""$dir""\033[0m(当前路由器环境推荐目录下安装)"
	fi

	$echo " 0 退出安装"
	echo -----------------------------------------------
	read -p "请输入相应数字 > " num
	#设置目录
	if [ -z $num ];then
		echo 安装已取消
		exit 1;
	elif [ "$num" = "1" ];then
		dir=/etc
	elif [ "$num" = "2" ];then
		dir=/usr/share
	elif [ "$num" = "3" ];then
		dir=~/.local/share
	elif [ "$num" = "4" ];then
		dir=/data
	elif [ "$num" = "5" ];then
		dir=/data/userdisk
	elif [ "$num" = "6" ];then
		dir=/jffs
	elif [ "$num" = "7" ];then
		dir=/etc/storage
	elif [ "$num" = "8" ];then
		echo -----------------------------------------------
		echo '可用路径 剩余空间:'
		df -h | awk '{print $6,$4}'| sed 1d 
		echo '路径是必须带 / 的格式，注意写入虚拟内存(/tmp,/opt,/sys...)的文件会在重启后消失！！！'
		read -p "请输入自定义路径 > " dir
		if [ -z "$dir" ];then
			$echo "\033[31m路径错误！请重新设置！\033[0m"
			setdir
		fi
	elif [ "$num" = "5" ];then
	 echo ""
	else
		echo 安装已取消！！！
		exit 1;
	fi

    if [ ! -w $dir ]; then
        $echo "\033[31m没有$dir目录写入权限！请重新设置！\033[0m" && sleep 1 && setdir
    else
        $echo "目标目录\033[32m$dir\033[0m空间剩余：$(dir_avail $dir)"
        read -p "确认安装？(1/0) > " res
        if [ -z $res ]; then
            echo 安装已取消
            exit 1
        elif [ "$res" = "1" ]; then
            luckydir=$dir/$luckPathSuff
            echo "luckdir:"$luckydir
        else
            echo 安装已取消
            exit 1
        fi
    fi
}

# 生成最终下载链接
getTargetFileURL() {

    echo "正在获取 $download_base_url/$version/$subdir/ 目录下的文件列表..."

    # 获取文件列表并筛选
    if curl --version >/dev/null 2>&1; then
        file_list=$(curl -s "$download_base_url/$version/$subdir/" | sed -n 's/.*href="\([^"]*\)".*/\1/p' | grep -iE 'tar\.gz' | grep "$cpucore" | grep "Linux" | sort -u)
    elif wget --version >/dev/null 2>&1; then
        file_list=$(wget -qO- "$download_base_url/$version/$subdir/" | sed -n 's/.*href="\([^"]*\)".*/\1/p' | grep -iE 'tar\.gz' | grep "$cpucore" | grep "Linux" | sort -u)
    else
        echo "无法获取文件列表，请检查下载地址是否正确！"
        exit 1
    fi

    # 过滤掉空行
    file_list=$(echo "$file_list" | grep -v '^$')

    if [ -z "$file_list" ]; then
        echo "未找到符合当前架构 ($cpucore) 的安装包 (tar.gz)！请检查目录结构！"
        exit 1
    fi

    # 直接判断安装包数量
    file_count=$(echo "$file_list" | wc -l)
    if [ "$file_count" -eq 1 ]; then
        selected_file=$(echo "$file_list")
        echo "自动选择唯一安装包: $selected_file"
    else
        echo "-----------------------------------------------"
        echo "可用的安装包文件："
        echo "$file_list" | awk '{print NR" "$0}'
        echo "-----------------------------------------------"

        # 选择安装包
        read -p "请输入对应的文件编号 > " num
        selected_file=$(echo "$file_list" | awk "NR==$num")

        if [ -z "$selected_file" ]; then
            echo -e "\033[31m输入错误，请重新选择！\033[0m"
            getTargetFileURL
            return
        fi
    fi

    # 拼接下载链接
    download_url="$download_base_url/$version/$subdir/$selected_file"
    echo "目标文件下载链接: $download_url"
}

# 下载文件
webget() {
    if curl --version >/dev/null 2>&1; then
        result=$(curl -w %{http_code} --connect-timeout 5 -L -o $1 $2)
        [ -n "$(echo $result | grep -e ^2)" ] && result="200"
    else
        if wget --version >/dev/null 2>&1; then
            wget -q --show-progress --no-check-certificate --timeout=3 -O $1 $2
        fi
        [ $? -eq 0 ] && result="200"
    fi
}

# 下载并解压文件
getFilesFromNetwork() {
    webget /tmp/lucky.tar.gz $download_url
    [ "$result" != "200" ] && echo "文件下载失败,请检查下载地址是否正确！" && exit 1
    echo -----------------------------------------------
    echo "开始解压文件！"
    mkdir -p $luckydir >/dev/null
    tar -zxvf '/tmp/lucky.tar.gz' -C $luckydir/
    [ $? -ne 0 ] && echo "文件解压失败！" && rm -rf /tmp/lucky.tar.gz && exit 1
    echo "已解压到 $luckydir"
    chmod +x $luckydir/lucky
    chmod +x $luckydir/scripts/*
    rm -rf /tmp/lucky.tar.gz
}

# 交互式菜单
luckyshMenu() {
    echo "*************************************************"
    echo "**                 欢迎使用                    **"
    echo "**                Lucky 管理脚本               **"
    echo "**                             by  古大羊      **"
    echo "**                          2025.02.17         **"
    echo "*************************************************"
    echo -e " 1 \033[32m安装\033[0m Lucky"
    echo -e " 2 \033[32m卸载\033[0m Lucky"
    echo -----------------------------------------------
    echo -e " 0 \033[0m退出脚本\033[0m"
    read -p "请输入对应数字 > " num
    case "$num" in
    0)
        echo "退出脚本"
        exit 0
        ;;
    1)
        echo "安装 Lucky..."
        install
        ;;
    2)
        echo "卸载 Lucky..."
        uninstall
        ;;
    *)
        echo -e "\033[31m请输入正确的数字！\033[0m"
        luckyshMenu
        ;;
    esac
}

downloadLucky(){
    echo "正在下载 Lucky 安装包..."
    webget /tmp/lucky.tar.gz $download_url
    if [ "$result" != "200" ]; then
        echo "文件下载失败, 请检查下载地址是否正确！"
        exit 1
    fi
    echo "Lucky 安装包下载完成！"
}

extractLucky(){
    echo "正在检查可用磁盘空间..."

    # 获取 tar.gz 文件大小（单位：字节）
    tar_file_size=$(stat -c %s /tmp/lucky.tar.gz)

    # 确保安装目录存在，若不存在，则使用其父目录
    if [ ! -d "$luckydir" ]; then
        luckydir_parent=$(dirname "$luckydir")
    else
        luckydir_parent="$luckydir"
    fi

    # 获取安装目录所在的挂载点
    mount_point=$(df "$luckydir_parent" 2>/dev/null | awk 'NR==2 {print $NF}')

    if [ -z "$mount_point" ]; then
        echo "错误：无法确定 $luckydir 的挂载点，请检查路径是否正确。"
        exit 1
    fi

    # 获取该挂载点的可用空间（单位：字节），兼容 BusyBox 版本 df
    available_space=$(( $(df -k "$mount_point" | awk 'NR==2 {print $4}') * 1024 ))

    # 计算解压后可能的大小（假设解压后是压缩包的 1.5 倍）
    estimated_size=$(( tar_file_size * 3 / 2 ))

    echo "压缩包大小: $tar_file_size 字节"
    echo "可用空间: $available_space 字节"
    echo "预估解压后大小: $estimated_size 字节"

    # 判断空间是否足够
    #if [ "$available_space" -lt "$estimated_size" ]; then
    if [ "$available_space" -gt 0 ] && [ "$available_space" -lt "$estimated_size" ]; then
        echo "磁盘空间不足！"
        echo "至少需要 $estimated_size 字节可用空间，但当前仅有 $available_space 字节。"
        exit 1
    fi

    echo "磁盘空间检查通过，开始解压文件..."
    mkdir -p "$luckydir" > /dev/null
    tar -zxvf '/tmp/lucky.tar.gz' -C "$luckydir/"
    if [ $? -ne 0 ]; then
        echo "文件解压失败！"
        rm -rf /tmp/lucky.tar.gz
        exit 1
    fi

    echo "已解压到 $luckydir"
    chmod +x "$luckydir/lucky"
    chmod +x "$luckydir/scripts/"*
    rm -rf /tmp/lucky.tar.gz
}

# 安装流程
install() {
    if [ -z "$download_base_url" ]; then
        echo -e "\033[31m错误: 未提供下载地址前缀！\033[0m"
        echo "使用方法: bash $0 <下载地址前缀>"
        exit 1
    fi
    select_version
    select_subdir

    getTargetFileURL

    setdir              #设置安装路径
    downloadLucky  # 下载 Lucky 安装包
    extractLucky   # 检查空间并解压安装包
    installSetProfile   #设置环境变量
    installSetInit      #设置开机启动

    echo "Lucky 安装完成！"
}

uninstallgetdir() {

    [ -w /opt/etc/profile ] && profile=/opt/etc/profile
    [ -w /jffs/configs/profile.add ] && profile=/jffs/configs/profile.add
    [ -w ~/.bashrc ] && profile=~/.bashrc
    [ -w /etc/profile ] && profile=/etc/profile

    luckydir=$(cat $profile | grep luckydir | awk -F "\"" '{print $2}')

    if [ -n "$luckydir" ]; then
        return
    fi

    if [ -n "$systype" ]; then
        [ "$systype" = "Padavan" ] && dir=/etc/storage
        [ "$systype" = "asusrouter" ] && dir=/jffs
        [ "$systype" = "mi_snapshot" ] && dir=/data
        luckydir=$dir/$luckPathSuff
    fi

}

# 卸载流程
uninstall() {
    uninstallgetdir #获取lucky安装路径

    systemctl disable $luckPathSuff.service >/dev/null 2>&1 &
    systemctl stop $luckPathSuff.service >/dev/null 2>&1 &

    #结束进程
    PID=$(pidof lucky) && [ -n "$PID" ] && kill -9 $PID >/dev/null 2>&1

    if [ -z $luckydir ]; then
        echo "找不到lucky文件夹，卸载中止"
        exit 0
    fi

    echo "删除 "$luckydir" 所有文件"
    read -p "确认删除？"$luckydir"所有文件(1/0) > " res
    if [ -z $res ]; then
        echo 卸载已取消
        exit 1
    elif [ "$res" = "1" ]; then
        rm -rf $luckydir
    else
        echo 卸载已取消
        exit 1
    fi

    [ -n "$initdir" ] && { #删除开机启动
        sed -i '/Lucky启动/'d $initdir 2>/dev/null
    }

    if [ "$systype" = "mi_snapshot" ]; then ##删除开机启动
        uci del firewall.Lucky
        uci commit firewall
    fi

    /etc/init.d/$luckPathSuff stop >/dev/null 2>&1
    rm -rf /etc/init.d/$luckPathSuff

    sed -i '/alias lucky=*/'d $profile
    sed -i '/export luckydir=*/'d $profile

    cronset '#lucky保守模式守护进程' #删除保守模式定时
}

#获取CPU结构
getcpucore

if [ -z "$cpucore" ]; then
    echo '未能正确识别当前系统CPU架构,请与作者联系'
    exit 1
fi

echo "当前CPU架构:"$cpucore

#判断linux环境, $systype ,$initdir
getLinuxSysType

[ -n "$initdir" ] && echo 'initdir:'$initdir
[ -n "$systype" ] && echo '当前处于路由器运行环境[' $systype']!'

# 运行菜单
luckyshMenu
