unbound一键安装脚本golang版

声明:本篇文章仅供学习研究,禁止用于非法途径,如不听劝告,产生的一切后果由使用者承担

package main

import (
	"bufio"
	"os"
	"os/exec"
	"runtime"
	"strings"

	"github.com/pterm/pterm"
)

const (
	downloadpath = "/root/unbound"
)

func main() {
	pterm.DefaultHeader.WithFullWidth().WithBackgroundStyle(pterm.NewStyle(pterm.BgCyan)).WithTextStyle(pterm.NewStyle(pterm.FgBlack)).Println("Unbound 一键安装脚本[V1.0.0]")
	pterm.DefaultHeader.WithFullWidth().WithBackgroundStyle(pterm.NewStyle(pterm.BgBlue)).WithTextStyle(pterm.NewStyle(pterm.FgBlack)).Println("--- XLX笔记 | www.xlxbk.cn ---")

	var options []string
	options = []string{
		"0 退出脚本",
		"1 安装Unbound",
		"2 升级Unbound",
	}
	selectedOption, _ := pterm.DefaultInteractiveSelect.WithOptions(options).Show()
	switch selectedOption {
	case "0 退出脚本":
		return
	case "1 安装Unbound":
		var mdstr string
		var packageManager string
		var baolist []string
		pterm.DefaultBasicText.Println("操作系统类型:" + pterm.LightMagenta(runtime.GOOS))
		pterm.DefaultBasicText.Println("CPU 架构:" + pterm.LightMagenta(runtime.GOARCH))
		if runtime.GOOS != "linux" {
			pterm.Error.Println("脚本只支持Linux系统")
			return
		}
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始检测系统使用的包管理器")
		packageManagers := []string{"apt", "yum", "dnf", "zypper", "pacman"}

		for _, manager := range packageManagers {
			cmd := exec.Command(manager, "--version")
			err := cmd.Run()
			if err == nil {
				pterm.DefaultBasicText.Printfln("系统使用的包管理器可能是: %s\n", manager)
				packageManager = manager
				break
			} else {
				pterm.Error.Printfln("命令 %s 未找到或执行出错: %v", manager, err)
			}
		}
		if packageManager == "" {
			pterm.Error.Println("系统未找到任何包管理器")
			return
		}
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始检测系统是否安装 wget")
		cmdwget := exec.Command("sh", "-c", "command -v wget")
		errwget := cmdwget.Run()
		if errwget == nil {
			pterm.DefaultBasicText.Println("系统已安装 wget")
		} else {
			pterm.Error.Println("系统未安装 wget")
			pterm.DefaultBasicText.Println("开始安装 wget")
			cmd := exec.Command(packageManager, "install", "-y", "wget")
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			err := cmd.Run()
			if err != nil {
				pterm.Error.Printfln("安装 wget 失败:%v", err)
				return
			}
		}

		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始检测系统是否安装 tar")
		cmdtar := exec.Command("sh", "-c", "command -v tar")
		errtar := cmdtar.Run()
		if errtar == nil {
			pterm.DefaultBasicText.Println("系统已安装 tar")
		} else {
			pterm.Error.Println("系统未安装 tar")
			pterm.DefaultBasicText.Println("开始安装 tar")
			cmd := exec.Command(packageManager, "install", "-y", "tar")
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			err := cmd.Run()
			if err != nil {
				pterm.Error.Printfln("安装 tar 失败:%v", err)
				return
			}
		}

		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始配置 Unbound 编译环境")
		result, _ := pterm.DefaultInteractiveConfirm.WithDefaultText("选择y会删除 /root 目录下 unbound 相关文件以及文件夹和 libevent 相关的文件和文件夹").WithTextStyle(pterm.NewStyle(pterm.FgYellow)).Show()
		if result {
			mdstr = "cd /root && rm -rf unbound* && rm -rf libevent* && rm -rf hiredis*"
			cmd := exec.Command("sh", "-c", mdstr)
			err := cmd.Run()
			if err != nil {
				pterm.Error.Printfln("删除 unbound 相关文件以及文件夹失败:%v", err)
				return
			}
		}

		mdstr = "mkdir -p " + downloadpath
		cmd := exec.Command("sh", "-c", mdstr)
		err := cmd.Run()
		if err != nil {
			pterm.Error.Printfln("创建 /root/unbound 目录失败:%v", err)
			return
		}

		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("请根据上述输出的包管理器选择对应的执行更新系统的命令")
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("由于部分系统会弹出交互式的更新所以需要手动执行这步操作")
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("apt update && apt upgrade -y")
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("yum update -y")
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("dnf update -y")
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("zypper update -y")
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("pacman -Syu")

		resultss, _ := pterm.DefaultInteractiveConfirm.WithDefaultText("是否已经手动更新了系统").WithTextStyle(pterm.NewStyle(pterm.FgYellow)).Show()

		if resultss {
		} else {
			pterm.Error.Println("请手动更新系统后再执行脚本")
			return
		}

		results, _ := pterm.DefaultInteractiveConfirm.WithDefaultText("是否已经手动配置了 Unbound 运行环境").WithTextStyle(pterm.NewStyle(pterm.FgYellow)).Show()

		if results {
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始下载 Unbound 源代码")

			mdstr = "cd /root && wget https://nlnetlabs.nl/downloads/unbound/unbound-latest.tar.gz && tar -zxvf unbound-latest.tar.gz -C " + downloadpath
			cmd := exec.Command("sh", "-c", mdstr)
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			err := cmd.Run()
			if err != nil {
				pterm.Error.Printfln("下载/解压 Unbound 失败:%v", err)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 源代码下载完成")

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始编译 Unbound")

			filename := checkfilename()
			mdstr = "cd " + downloadpath + "/" + filename + " && ./configure --enable-subnet --with-libevent --with-libhiredis --enable-cachedb && make && make install"
			cmdinstall := exec.Command("sh", "-c", mdstr)
			cmdinstall.Stdout = os.Stdout
			cmdinstall.Stderr = os.Stderr
			errinstall := cmdinstall.Run()
			if errinstall != nil {
				pterm.Error.Printfln("编译安装 Unbound 失败:%v", errinstall)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 编译安装完成")

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始配置 Unbound")

			mdstr = "cd /usr/local/etc/unbound && wget -O root.hints https://www.internic.net/domain/named.root && touch unbound.log && chmod 666 unbound.log && rm -rf unbound.conf && wget https://oss.xlxbk.cn/unbound.conf && chmod 644 unbound.conf"
			cmdconf := exec.Command("sh", "-c", mdstr)
			cmdconf.Stdout = os.Stdout
			cmdconf.Stderr = os.Stderr
			errconf := cmdconf.Run()
			if errconf != nil {
				pterm.Error.Printfln("下载 Unbound 相关配置文件失败:%v", errconf)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 配置文件下载完成")

			mdstr = "chmod 777 /usr/local/etc/unbound"
			cmdchmod := exec.Command("sh", "-c", mdstr)
			cmdchmod.Stdout = os.Stdout
			cmdchmod.Stderr = os.Stderr
			errchmod := cmdchmod.Run()
			if errchmod != nil {
				pterm.Error.Printfln("赋予目录权限失败:%v", errchmod)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 配置文件赋予权限完成")

			mdstr = "unbound-anchor"
			cmdunbchor := exec.Command("sh", "-c", mdstr)
			cmdunbchor.Stdout = os.Stdout
			cmdunbchor.Stderr = os.Stderr
			errunbchor := cmdunbchor.Run()
			if errunbchor != nil {
				mdstr = "ls /usr/local/etc/unbound/root.key"
				cmdlsrootkey := exec.Command("sh", "-c", mdstr)
				cmdlsrootkey.Stdout = os.Stdout
				cmdlsrootkey.Stderr = os.Stderr
				errlsrootkey := cmdlsrootkey.Run()
				if errlsrootkey != nil {
					pterm.Error.Printfln("配置Unbound DNSSEC 失败:%v", errunbchor)
					return
				}
			}
			pterm.DefaultBasicText.Println("Unbound DNSSEC 配置完成")

			mdstr = "unbound-control-setup"
			cmdunbcoup := exec.Command("sh", "-c", mdstr)
			cmdunbcoup.Stdout = os.Stdout
			cmdunbcoup.Stderr = os.Stderr
			errunbcoup := cmdunbcoup.Run()
			if errunbcoup != nil {
				pterm.Error.Printfln("配置Unbound 远程控制失败:%v", errunbcoup)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 远程控制配置完成")

			if !checkUserExists("unbound") {
				mdstr = "groupadd unbound && useradd -m -g unbound -s /bin/false unbound"
				cmduser := exec.Command("sh", "-c", mdstr)
				cmduser.Stdout = os.Stdout
				cmduser.Stderr = os.Stderr
				erruser := cmduser.Run()
				if erruser != nil {
					pterm.Error.Printfln("创建 unbound 用户失败:%v", erruser)
					return
				}
				pterm.DefaultBasicText.Println("创建 unbound 用户完成")
			}

			mdstr = "cd /lib/systemd/system && wget https://oss.xlxbk.cn/unbound.service && chmod 644 unbound.service && systemctl daemon-reload && systemctl enable unbound"
			cmdserv := exec.Command("sh", "-c", mdstr)
			cmdserv.Stdout = os.Stdout
			cmdserv.Stderr = os.Stderr
			errserv := cmdserv.Run()
			if errserv != nil {
				pterm.Error.Printfln("配置 Unbound 服务失败:%v", errserv)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 服务配置完成")

			mdstr = "systemctl start unbound"
			cmdstart := exec.Command("sh", "-c", mdstr)
			cmdstart.Stdout = os.Stdout
			cmdstart.Stderr = os.Stderr
			errstart := cmdstart.Run()
			if errstart != nil {
				pterm.Error.Printfln("启动 Unbound 服务失败:%v", errstart)
				return
			}
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.BgLightRed)).Println("Unbound 默认目录 /usr/local/etc/unbound 配置文件、日志什么的都在这个目录有特殊需求可以自行更改配置文件")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.BgLightRed)).Println("Unbound 监听端口 5353")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.BgLightRed)).Println("Unbound 监听IP 所有IP")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.BgLightRed)).Println("使用 lsof -i:5353 可以检测Unbound是否启动成功")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.BgLightRed)).Println("如果启动失败,请运行 systemctl status unbound 截图发送给开发者")
		} else {
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("安装 Unbound 编译所需依赖")
			if packageManager == "apt" {
				baolist = []string{
					"build-essential",
					"libssl-dev",
					"libexpat1-dev",
					"bison",
					"flex",
					"libhiredis-dev",
				}
				for _, bao := range baolist {
					mdstr = "command -v " + bao
					cmdisinstall := exec.Command("sh", "-c", mdstr)
					if err := cmdisinstall.Run(); err == nil {
						continue
					} else {
						mdstr = "apt install -y " + bao
						cmd := exec.Command("sh", "-c", mdstr)
						cmd.Stdout = os.Stdout
						cmd.Stderr = os.Stderr
						err := cmd.Run()
						if err != nil {
							pterm.Error.Printfln("使用 apt 安装 Unbound 编译依赖 %v 失败:%v", bao, err)
							return
						}
					}

				}
			} else if packageManager == "yum" {
				baolist = []string{
					"gcc",
					"openssl-devel",
					"expat-devel",
					"libevent-devel",
					"make",
					"hiredis",
					"hiredis-devel",
				}
				for _, bao := range baolist {
					if bao == "hiredis" {
						mdstr = "yum search hiredis"
						cmdsearch := exec.Command("sh", "-c", mdstr)
						cmdsearch.Stdout = os.Stdout
						cmdsearch.Stderr = os.Stderr
						output, errsearch := cmdsearch.CombinedOutput()
						if errsearch != nil {
							pterm.Error.Printfln("运行 yum 命令时发生错误: %v", errsearch)
						}
						if strings.Contains(string(output), "hiredis") {
							mdstr = "command -v " + bao
							cmdisinstall := exec.Command("sh", "-c", mdstr)
							if err := cmdisinstall.Run(); err == nil {
								continue
							} else {
								mdstr = "yum install -y " + bao
								cmd := exec.Command("sh", "-c", mdstr)
								cmd.Stdout = os.Stdout
								cmd.Stderr = os.Stderr
								err := cmd.Run()
								if err != nil {
									pterm.Error.Printfln("使用 yum 安装 Unbound 编译依赖%v失败:%v", bao, err)
									return
								}
							}
						} else {

							cmdishiredis := exec.Command("find", "/", "-name", "libhiredis.so.*")
							output, errishiredis := cmdishiredis.CombinedOutput()
							if errishiredis != nil {
								pterm.Error.Printfln("执行寻找 libhiredis.so.* 失败:%v", errishiredis)
								return
							}

							if strings.Contains(string(output), "libhiredis") {
								pterm.DefaultBasicText.Println("hiredis 已经安装过了")
								if !checkldso() {
									mdstr = "echo '/usr/local/lib' >> /etc/ld.so.conf && ldconfig"
									cmd := exec.Command("sh", "-c", mdstr)
									cmd.Stdout = os.Stdout
									cmd.Stderr = os.Stderr
									if err := cmd.Run(); err == nil {
										pterm.DefaultBasicText.Println("hiredis 配置成功")
									} else {
										pterm.Error.Printfln("hiredis 配置失败:%v", err)
										return
									}
								}
								break
							} else {
								mdstr = "cd /root && wget https://oss.xlxbk.cn/hiredis-1.2.0.tar.gz && tar zxvf hiredis-1.2.0.tar.gz -C" + downloadpath + " && cd " + downloadpath + "/hiredis-1.2.0 && make && make install"
								cmdhiredis := exec.Command("sh", "-c", mdstr)
								cmdhiredis.Stdout = os.Stdout
								cmdhiredis.Stderr = os.Stderr
								if err := cmdhiredis.Run(); err == nil {
									pterm.DefaultBasicText.Println("hiredis 编译安装成功")
								} else {
									pterm.Error.Printfln("hiredis 编译安装失败:%v", err)
									return
								}
								if !checkldso() {
									mdstr = "echo '/usr/local/lib' >> /etc/ld.so.conf && ldconfig"
									cmd := exec.Command("sh", "-c", mdstr)
									cmd.Stdout = os.Stdout
									cmd.Stderr = os.Stderr
									if err := cmd.Run(); err == nil {
										pterm.DefaultBasicText.Println("hiredis 配置成功")
									} else {
										pterm.Error.Printfln("hiredis 配置失败:%v", err)
										return
									}
								}
								break
							}

						}

					} else {

						mdstr = "command -v " + bao
						cmdisinstall := exec.Command("sh", "-c", mdstr)
						if err := cmdisinstall.Run(); err == nil {
							continue
						} else {
							mdstr = "yum install -y " + bao
							cmd := exec.Command("sh", "-c", mdstr)
							cmd.Stdout = os.Stdout
							cmd.Stderr = os.Stderr
							err := cmd.Run()
							if err != nil {
								pterm.Error.Printfln("使用 yum 安装 Unbound 编译依赖 %v 失败:%v", bao, err)
								return
							}
						}
					}

				}

			} else if packageManager == "dnf" {
				baolist = []string{
					"gcc",
					"openssl-devel",
					"expat-devel",
					"libevent-devel",
					"make",
					"hiredis",
					"hiredis-devel",
				}
				for _, bao := range baolist {
					mdstr = "command -v " + bao
					cmdisinstall := exec.Command("sh", "-c", mdstr)
					cmdisinstall.Stdout = os.Stdout
					cmdisinstall.Stderr = os.Stderr
					if err := cmdisinstall.Run(); err == nil {
						continue
					} else {
						mdstr = "dnf install -y " + bao
						cmd := exec.Command("sh", "-c", mdstr)
						cmd.Stdout = os.Stdout
						cmd.Stderr = os.Stderr
						err := cmd.Run()
						if err != nil {
							pterm.Error.Printfln("使用 dnf 安装 Unbound 编译依赖 %v 失败:%v", bao, err)
							return
						}
					}
				}

			} else if packageManager == "zypper" {
				mdstr = "zypper install -t pattern -y devel_C_C++"
				cmd := exec.Command("sh", "-c", mdstr)
				cmd.Stdout = os.Stdout
				cmd.Stderr = os.Stderr
				err := cmd.Run()
				if err != nil {
					pterm.Error.Printfln("使用 zypper 安装 Unbound 开发工具和编译器失败:%v", err)
					return
				}
				mdstr = "zypper install -y libevent-devel openssl-devel libexpat-devel libuv-devel libhiredis-devel"
				cmd = exec.Command("sh", "-c", mdstr)
				cmd.Stdout = os.Stdout
				cmd.Stderr = os.Stderr
				err = cmd.Run()
				if err != nil {
					pterm.Error.Printfln("使用 zypper 安装 Unbound 必要的依赖包失败:%v", err)
					return
				}
			} else if packageManager == "pacman" {
				mdstr = "pacman -S -y base-devel libevent openssl expat libuv hiredis"
				cmd := exec.Command("sh", "-c", mdstr)
				cmd.Stdout = os.Stdout
				cmd.Stderr = os.Stderr
				err := cmd.Run()
				if err != nil {
					pterm.Error.Printfln("使用 pacman 安装 Unbound 编译依赖失败:%v", err)
					return
				}
			}
			pterm.DefaultBasicText.Println("Unbound 编译所需依赖安装完成")

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始安装 libevent")

			cmdislibevent := exec.Command("find", "/", "-name", "libevent-2.1.so.*")
			output, errislibevent := cmdislibevent.CombinedOutput()

			if errislibevent != nil {
				pterm.Error.Printfln("执行寻找 libevent-2.1.so.* 失败:%v", errislibevent)
				return
			}

			if strings.Contains(string(output), "libevent-2.1.so") {
				pterm.DefaultBasicText.Println("libevent 已经安装过了")
			} else {
				mdstr = "cd /root && wget https://oss.xlxbk.cn/libevent-2.1.12-stable.tar.gz && tar -zxvf libevent-2.1.12-stable.tar.gz && cd libevent-2.1.12-stable && ./configure && make && make install"
				cmdlibevent := exec.Command("sh", "-c", mdstr)
				cmdlibevent.Stdout = os.Stdout
				cmdlibevent.Stderr = os.Stderr
				errlibevent := cmdlibevent.Run()
				if errlibevent != nil {
					pterm.Error.Printfln("编译安装 libevent 失败:%v", errlibevent)
					return
				}
				pterm.DefaultBasicText.Println("libevent 安装完成")
			}

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始下载 Unbound 源代码")

			mdstr = "cd /root && wget https://nlnetlabs.nl/downloads/unbound/unbound-latest.tar.gz && tar -zxvf unbound-latest.tar.gz -C " + downloadpath
			cmd := exec.Command("sh", "-c", mdstr)
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			err := cmd.Run()
			if err != nil {
				pterm.Error.Printfln("下载/解压 Unbound 失败:%v", err)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 源代码下载完成")

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始编译 Unbound")

			filename := checkfilename()
			mdstr = "cd " + downloadpath + "/" + filename + " && ./configure --enable-subnet --with-libevent --with-libhiredis --enable-cachedb && make && make install"
			cmdinstall := exec.Command("sh", "-c", mdstr)
			cmdinstall.Stdout = os.Stdout
			cmdinstall.Stderr = os.Stderr
			errinstall := cmdinstall.Run()
			if errinstall != nil {
				pterm.Error.Printfln("编译安装 Unbound 失败:%v", errinstall)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 编译安装完成")

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始配置 Unbound")

			mdstr = "cd /usr/local/etc/unbound && wget -O root.hints https://www.internic.net/domain/named.root && touch unbound.log && chmod 666 unbound.log && rm -rf unbound.conf && wget https://oss.xlxbk.cn/unbound.conf && chmod 644 unbound.conf"
			cmdconf := exec.Command("sh", "-c", mdstr)
			cmdconf.Stdout = os.Stdout
			cmdconf.Stderr = os.Stderr
			errconf := cmdconf.Run()
			if errconf != nil {
				pterm.Error.Printfln("下载 Unbound 相关配置文件失败:%v", errconf)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 配置文件下载完成")

			mdstr = "chmod 777 /usr/local/etc/unbound"
			cmdchmod := exec.Command("sh", "-c", mdstr)
			cmdchmod.Stdout = os.Stdout
			cmdchmod.Stderr = os.Stderr
			errchmod := cmdchmod.Run()
			if errchmod != nil {
				pterm.Error.Printfln("赋予目录权限失败:%v", errchmod)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 配置文件赋予权限完成")

			mdstr = "unbound-anchor"
			cmdunbchor := exec.Command("sh", "-c", mdstr)
			cmdunbchor.Stdout = os.Stdout
			cmdunbchor.Stderr = os.Stderr
			errunbchor := cmdunbchor.Run()
			if errunbchor != nil {
				mdstr = "ls /usr/local/etc/unbound/root.key"
				cmdlsrootkey := exec.Command("sh", "-c", mdstr)
				cmdlsrootkey.Stdout = os.Stdout
				cmdlsrootkey.Stderr = os.Stderr
				errlsrootkey := cmdlsrootkey.Run()
				if errlsrootkey != nil {
					pterm.Error.Printfln("配置Unbound DNSSEC 失败:%v", errunbchor)
					return
				}
			}
			pterm.DefaultBasicText.Println("Unbound DNSSEC 配置完成")

			mdstr = "unbound-control-setup"
			cmdunbcoup := exec.Command("sh", "-c", mdstr)
			cmdunbcoup.Stdout = os.Stdout
			cmdunbcoup.Stderr = os.Stderr
			errunbcoup := cmdunbcoup.Run()
			if errunbcoup != nil {
				pterm.Error.Printfln("配置Unbound 远程控制失败:%v", errunbcoup)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 远程控制配置完成")

			if !checkUserExists("unbound") {
				mdstr = "groupadd unbound && useradd -m -g unbound -s /bin/false unbound"
				cmduser := exec.Command("sh", "-c", mdstr)
				cmduser.Stdout = os.Stdout
				cmduser.Stderr = os.Stderr
				erruser := cmduser.Run()
				if erruser != nil {
					pterm.Error.Printfln("创建 unbound 用户失败:%v", erruser)
					return
				}
				pterm.DefaultBasicText.Println("创建 unbound 用户完成")
			}

			mdstr = "cd /lib/systemd/system && wget https://oss.xlxbk.cn/unbound.service && chmod 644 unbound.service && systemctl daemon-reload && systemctl enable unbound"
			cmdserv := exec.Command("sh", "-c", mdstr)
			cmdserv.Stdout = os.Stdout
			cmdserv.Stderr = os.Stderr
			errserv := cmdserv.Run()
			if errserv != nil {
				pterm.Error.Printfln("配置 Unbound 服务失败:%v", errserv)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 服务配置完成")

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始安装 redis")

			cmdisredis := exec.Command("sh", "-c", "command -v redis")
			cmdisredis.Stdout = os.Stdout
			cmdisredis.Stderr = os.Stderr
			errisredis := cmdisredis.Run()
			if errisredis == nil {
				pterm.DefaultBasicText.Println("redis 已经安装过了")
			} else {
				cmdredis := exec.Command(packageManager, "install", "-y", "redis")
				cmdredis.Stdout = os.Stdout
				cmdredis.Stderr = os.Stderr
				errredis := cmdredis.Run()
				if errredis != nil {
					pterm.Error.Printfln("安装 redis 失败:%v", err)
					return
				}
				pterm.DefaultBasicText.Println("redis 安装完成")
			}

			mdstr = "systemctl start unbound"
			cmdstart := exec.Command("sh", "-c", mdstr)
			cmdstart.Stdout = os.Stdout
			cmdstart.Stderr = os.Stderr
			errstart := cmdstart.Run()
			if errstart != nil {
				pterm.Error.Printfln("启动 Unbound 服务失败:%v", errstart)
				return
			}
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).WithStyle(pterm.NewStyle()).Println("Unbound 默认目录 /usr/local/etc/unbound 配置文件、日志什么的都在这个目录有特殊需求可以自行更改配置文件")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("Unbound 监听端口 5363")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("Unbound 监听IP 所有IP")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("使用 lsof -i:5353 可以检测Unbound是否启动成功")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("如果启动失败,请运行 systemctl status unbound 截图发送给开发者")

		}

	case "2 升级Unbound":
		var mdstr string
		result, _ := pterm.DefaultInteractiveConfirm.WithDefaultText("选择y会删除 /root 目录下 unbound 相关文件和文件夹").WithTextStyle(pterm.NewStyle(pterm.FgYellow)).Show()
		if result {
			mdstr = "cd /root && rm -rf unbound*"
			cmd := exec.Command("sh", "-c", mdstr)
			err := cmd.Run()
			if err != nil {
				pterm.Error.Printfln("删除 unbound 相关文件以及文件夹失败:%v", err)
				return
			}
		}

		mdstr = "mkdir -p " + downloadpath
		cmdmkdir := exec.Command("sh", "-c", mdstr)
		errmkdir := cmdmkdir.Run()
		if errmkdir != nil {
			pterm.Error.Printfln("创建 /root/unbound 目录失败:%v", errmkdir)
			return
		}

		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始下载 Unbound 源代码")

		mdstr = "cd /root && wget https://nlnetlabs.nl/downloads/unbound/unbound-latest.tar.gz && tar -zxvf unbound-latest.tar.gz -C " + downloadpath
		cmd := exec.Command("sh", "-c", mdstr)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err := cmd.Run()
		if err != nil {
			pterm.Error.Printfln("下载/解压 Unbound 失败:%v", err)
			return
		}
		pterm.DefaultBasicText.Println("Unbound 源代码下载完成")

		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始编译 Unbound")

		filename := checkfilename()
		mdstr = "cd " + downloadpath + "/" + filename + " && ./configure --enable-subnet --with-libevent --with-libhiredis --enable-cachedb && make && make install"
		cmdinstall := exec.Command("sh", "-c", mdstr)
		cmdinstall.Stdout = os.Stdout
		cmdinstall.Stderr = os.Stderr
		errinstall := cmdinstall.Run()
		if errinstall != nil {
			pterm.Error.Printfln("编译安装 Unbound 失败:%v", errinstall)
			return
		}
		pterm.DefaultBasicText.Println("Unbound 编译安装完成")

		mdstr = "systemctl restart unbound"
		cmdstart := exec.Command("sh", "-c", mdstr)
		cmdstart.Stdout = os.Stdout
		cmdstart.Stderr = os.Stderr
		errstart := cmdstart.Run()
		if errstart != nil {
			pterm.Error.Printfln("重新启动 Unbound 服务失败:%v", errstart)
			return
		}
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("Unbound 升级完成")
	}
}

func checkUserExists(username string) bool {
	file, err := os.Open("/etc/passwd")
	if err != nil {
		pterm.Error.Printfln("打开/etc/passwd文件失败:%v", err)
		return false
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		fields := strings.Split(line, ":")
		if len(fields) > 0 && fields[0] == username {
			return true
		}
	}

	if err := scanner.Err(); err != nil {
		pterm.Error.Printfln("读取/etc/passwd文件失败:%v", err)
	}
	return false
}

func checkfilename() string {

	entries, _ := os.ReadDir(downloadpath)
	for _, entry := range entries {
		if strings.Contains(entry.Name(), "unbound") {
			return entry.Name()
		}
	}
	return ""
}

func checkldso() bool {
	file, err := os.Open("/etc/ld.so.conf")
	if err != nil {
		pterm.Error.Printfln("打开 /etc/ld.so.conf 文件失败:%v", err)
		return false
	}
	defer func(file *os.File) {
		err = file.Close()
		if err != nil {
			pterm.Error.Printfln("关闭 /etc/ld.so.conf 文件失败:%v", err)
		}
	}(file)

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		if strings.Contains(line, "/usr/local/lib") {
			return true
		}
	}
	return false
}
package main

import (
	"bufio"
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"runtime"
	"strings"

	"github.com/valyala/fastjson"

	"github.com/pterm/pterm"
)

const (
	downloadpath = "/root/unbound"
)

func main() {
	pterm.DefaultHeader.WithFullWidth().WithBackgroundStyle(pterm.NewStyle(pterm.BgCyan)).WithTextStyle(pterm.NewStyle(pterm.FgBlack)).Println("Unbound 一键安装脚本[V1.0.1]")
	pterm.DefaultHeader.WithFullWidth().WithBackgroundStyle(pterm.NewStyle(pterm.BgBlue)).WithTextStyle(pterm.NewStyle(pterm.FgBlack)).Println("--- XLX笔记 | www.xlxbk.cn ---")

	var options []string
	options = []string{
		"0 退出脚本",
		"1 安装Unbound+AdGuardHome",
		"2 升级Unbound",
	}
	selectedOption, _ := pterm.DefaultInteractiveSelect.WithOptions(options).Show()
	switch selectedOption {
	case "0 退出脚本":
		return
	case "1 安装Unbound+AdGuardHome":
		var mdstr string
		var packageManager string
		var baolist []string
		pterm.DefaultBasicText.Println("操作系统类型:" + pterm.LightMagenta(runtime.GOOS))
		pterm.DefaultBasicText.Println("CPU 架构:" + pterm.LightMagenta(runtime.GOARCH))
		if runtime.GOOS != "linux" {
			pterm.Error.Println("脚本只支持Linux系统")
			return
		}
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始检测系统使用的包管理器")
		packageManagers := []string{"apt", "yum", "dnf", "zypper", "pacman"}

		for _, manager := range packageManagers {
			cmd := exec.Command(manager, "--version")
			err := cmd.Run()
			if err == nil {
				pterm.DefaultBasicText.Printfln("系统使用的包管理器可能是: %s\n", manager)
				packageManager = manager
				break
			} else {
				pterm.Error.Printfln("命令 %s 未找到或执行出错: %v", manager, err)
			}
		}
		if packageManager == "" {
			pterm.Error.Println("系统未找到任何包管理器")
			return
		}
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始检测系统是否安装 wget")
		cmdwget := exec.Command("sh", "-c", "command -v wget")
		errwget := cmdwget.Run()
		if errwget == nil {
			pterm.DefaultBasicText.Println("系统已安装 wget")
		} else {
			pterm.Error.Println("系统未安装 wget")
			pterm.DefaultBasicText.Println("开始安装 wget")
			cmd := exec.Command(packageManager, "install", "-y", "wget")
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			err := cmd.Run()
			if err != nil {
				pterm.Error.Printfln("安装 wget 失败:%v", err)
				return
			}
		}

		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始检测系统是否安装 tar")
		cmdtar := exec.Command("sh", "-c", "command -v tar")
		errtar := cmdtar.Run()
		if errtar == nil {
			pterm.DefaultBasicText.Println("系统已安装 tar")
		} else {
			pterm.Error.Println("系统未安装 tar")
			pterm.DefaultBasicText.Println("开始安装 tar")
			cmd := exec.Command(packageManager, "install", "-y", "tar")
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			err := cmd.Run()
			if err != nil {
				pterm.Error.Printfln("安装 tar 失败:%v", err)
				return
			}
		}

		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始配置 Unbound 编译环境")
		result, _ := pterm.DefaultInteractiveConfirm.WithDefaultText("选择y会删除 /root 目录下 unbound 相关文件以及文件夹和 libevent 相关的文件和文件夹").WithTextStyle(pterm.NewStyle(pterm.FgYellow)).Show()
		if result {
			mdstr = "cd /root && rm -rf unbound* && rm -rf libevent* && rm -rf hiredis*"
			cmd := exec.Command("sh", "-c", mdstr)
			err := cmd.Run()
			if err != nil {
				pterm.Error.Printfln("删除 unbound 相关文件以及文件夹失败:%v", err)
				return
			}
		}

		mdstr = "mkdir -p " + downloadpath
		cmd := exec.Command("sh", "-c", mdstr)
		err := cmd.Run()
		if err != nil {
			pterm.Error.Printfln("创建 /root/unbound 目录失败:%v", err)
			return
		}

		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("请根据上述输出的包管理器选择对应的执行更新系统的命令")
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("由于部分系统会弹出交互式的更新所以需要手动执行这步操作")
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("apt update && apt upgrade -y")
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("yum update -y")
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("dnf update -y")
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("zypper update -y")
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("pacman -Syu")

		resultss, _ := pterm.DefaultInteractiveConfirm.WithDefaultText("是否已经手动更新了系统").WithTextStyle(pterm.NewStyle(pterm.FgYellow)).Show()

		if resultss {
		} else {
			pterm.Error.Println("请手动更新系统后再执行脚本")
			return
		}

		results, _ := pterm.DefaultInteractiveConfirm.WithDefaultText("是否已经手动配置了 Unbound 运行环境").WithTextStyle(pterm.NewStyle(pterm.FgYellow)).Show()

		if results {
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始下载 Unbound 源代码")

			mdstr = "cd /root && wget https://nlnetlabs.nl/downloads/unbound/unbound-latest.tar.gz && tar -zxvf unbound-latest.tar.gz -C " + downloadpath
			cmd := exec.Command("sh", "-c", mdstr)
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			err := cmd.Run()
			if err != nil {
				pterm.Error.Printfln("下载/解压 Unbound 失败:%v", err)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 源代码下载完成")

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始编译 Unbound")

			filename := checkfilename()
			mdstr = "cd " + downloadpath + "/" + filename + " && ./configure --enable-subnet --with-libevent --with-libhiredis --enable-cachedb && make && make install"
			cmdinstall := exec.Command("sh", "-c", mdstr)
			cmdinstall.Stdout = os.Stdout
			cmdinstall.Stderr = os.Stderr
			errinstall := cmdinstall.Run()
			if errinstall != nil {
				pterm.Error.Printfln("编译安装 Unbound 失败:%v", errinstall)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 编译安装完成")

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始配置 Unbound")

			mdstr = "cd /usr/local/etc/unbound && wget -O root.hints https://www.internic.net/domain/named.root && touch unbound.log && chmod 666 unbound.log && rm -rf unbound.conf && wget https://oss.xlxbk.cn/unbound.conf && chmod 644 unbound.conf"
			cmdconf := exec.Command("sh", "-c", mdstr)
			cmdconf.Stdout = os.Stdout
			cmdconf.Stderr = os.Stderr
			errconf := cmdconf.Run()
			if errconf != nil {
				pterm.Error.Printfln("下载 Unbound 相关配置文件失败:%v", errconf)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 配置文件下载完成")

			mdstr = "chmod 777 /usr/local/etc/unbound"
			cmdchmod := exec.Command("sh", "-c", mdstr)
			cmdchmod.Stdout = os.Stdout
			cmdchmod.Stderr = os.Stderr
			errchmod := cmdchmod.Run()
			if errchmod != nil {
				pterm.Error.Printfln("赋予目录权限失败:%v", errchmod)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 配置文件赋予权限完成")

			mdstr = "unbound-anchor"
			cmdunbchor := exec.Command("sh", "-c", mdstr)
			cmdunbchor.Stdout = os.Stdout
			cmdunbchor.Stderr = os.Stderr
			errunbchor := cmdunbchor.Run()
			if errunbchor != nil {
				mdstr = "ls /usr/local/etc/unbound/root.key"
				cmdlsrootkey := exec.Command("sh", "-c", mdstr)
				cmdlsrootkey.Stdout = os.Stdout
				cmdlsrootkey.Stderr = os.Stderr
				errlsrootkey := cmdlsrootkey.Run()
				if errlsrootkey != nil {
					pterm.Error.Printfln("配置Unbound DNSSEC 失败:%v", errunbchor)
					return
				}
			}
			pterm.DefaultBasicText.Println("Unbound DNSSEC 配置完成")

			mdstr = "unbound-control-setup"
			cmdunbcoup := exec.Command("sh", "-c", mdstr)
			cmdunbcoup.Stdout = os.Stdout
			cmdunbcoup.Stderr = os.Stderr
			errunbcoup := cmdunbcoup.Run()
			if errunbcoup != nil {
				pterm.Error.Printfln("配置Unbound 远程控制失败:%v", errunbcoup)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 远程控制配置完成")

			if !checkUserExists("unbound") {
				mdstr = "groupadd unbound && useradd -m -g unbound -s /bin/false unbound"
				cmduser := exec.Command("sh", "-c", mdstr)
				cmduser.Stdout = os.Stdout
				cmduser.Stderr = os.Stderr
				erruser := cmduser.Run()
				if erruser != nil {
					pterm.Error.Printfln("创建 unbound 用户失败:%v", erruser)
					return
				}
				pterm.DefaultBasicText.Println("创建 unbound 用户完成")
			}

			mdstr = "cd /lib/systemd/system && wget https://oss.xlxbk.cn/unbound.service && chmod 644 unbound.service && systemctl daemon-reload && systemctl enable unbound"
			cmdserv := exec.Command("sh", "-c", mdstr)
			cmdserv.Stdout = os.Stdout
			cmdserv.Stderr = os.Stderr
			errserv := cmdserv.Run()
			if errserv != nil {
				pterm.Error.Printfln("配置 Unbound 服务失败:%v", errserv)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 服务配置完成")

			mdstr = "systemctl start unbound"
			cmdstart := exec.Command("sh", "-c", mdstr)
			cmdstart.Stdout = os.Stdout
			cmdstart.Stderr = os.Stderr
			errstart := cmdstart.Run()
			if errstart != nil {
				pterm.Error.Printfln("启动 Unbound 服务失败:%v", errstart)
				return
			}
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.BgLightRed)).Println("Unbound 默认目录 /usr/local/etc/unbound 配置文件、日志什么的都在这个目录有特殊需求可以自行更改配置文件")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.BgLightRed)).Println("Unbound 监听端口 5353")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.BgLightRed)).Println("Unbound 监听IP 所有IP")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.BgLightRed)).Println("使用 lsof -i:5353 可以检测Unbound是否启动成功")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.BgLightRed)).Println("如果启动失败,请运行 systemctl status unbound 截图发送给开发者")
		} else {
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("安装 Unbound 编译所需依赖")
			if packageManager == "apt" {
				baolist = []string{
					"build-essential",
					"libssl-dev",
					"libexpat1-dev",
					"bison",
					"flex",
					"libhiredis-dev",
				}
				for _, bao := range baolist {
					mdstr = "command -v " + bao
					cmdisinstall := exec.Command("sh", "-c", mdstr)
					if err := cmdisinstall.Run(); err == nil {
						continue
					} else {
						mdstr = "apt install -y " + bao
						cmd := exec.Command("sh", "-c", mdstr)
						cmd.Stdout = os.Stdout
						cmd.Stderr = os.Stderr
						err := cmd.Run()
						if err != nil {
							pterm.Error.Printfln("使用 apt 安装 Unbound 编译依赖 %v 失败:%v", bao, err)
							return
						}
					}

				}
			} else if packageManager == "yum" {
				baolist = []string{
					"gcc",
					"openssl-devel",
					"expat-devel",
					"libevent-devel",
					"make",
					"hiredis",
					"hiredis-devel",
				}
				for _, bao := range baolist {
					if bao == "hiredis" {
						mdstr = "yum search hiredis"
						cmdsearch := exec.Command("sh", "-c", mdstr)
						cmdsearch.Stdout = os.Stdout
						cmdsearch.Stderr = os.Stderr
						output, errsearch := cmdsearch.CombinedOutput()
						if errsearch != nil {
							pterm.Error.Printfln("运行 yum 命令时发生错误: %v", errsearch)
						}
						if strings.Contains(string(output), "hiredis") {
							mdstr = "command -v " + bao
							cmdisinstall := exec.Command("sh", "-c", mdstr)
							if err := cmdisinstall.Run(); err == nil {
								continue
							} else {
								mdstr = "yum install -y " + bao
								cmd := exec.Command("sh", "-c", mdstr)
								cmd.Stdout = os.Stdout
								cmd.Stderr = os.Stderr
								err := cmd.Run()
								if err != nil {
									pterm.Error.Printfln("使用 yum 安装 Unbound 编译依赖%v失败:%v", bao, err)
									return
								}
							}
						} else {

							cmdishiredis := exec.Command("find", "/", "-name", "libhiredis.so.*")
							output, errishiredis := cmdishiredis.CombinedOutput()
							if errishiredis != nil {
								pterm.Error.Printfln("执行寻找 libhiredis.so.* 失败:%v", errishiredis)
								return
							}

							if strings.Contains(string(output), "libhiredis") {
								pterm.DefaultBasicText.Println("hiredis 已经安装过了")
								if !checkldso() {
									mdstr = "echo '/usr/local/lib' >> /etc/ld.so.conf && ldconfig"
									cmd := exec.Command("sh", "-c", mdstr)
									cmd.Stdout = os.Stdout
									cmd.Stderr = os.Stderr
									if err := cmd.Run(); err == nil {
										pterm.DefaultBasicText.Println("hiredis 配置成功")
									} else {
										pterm.Error.Printfln("hiredis 配置失败:%v", err)
										return
									}
								}
								break
							} else {
								mdstr = "cd /root && wget https://oss.xlxbk.cn/hiredis-1.2.0.tar.gz && tar zxvf hiredis-1.2.0.tar.gz -C" + downloadpath + " && cd " + downloadpath + "/hiredis-1.2.0 && make && make install"
								cmdhiredis := exec.Command("sh", "-c", mdstr)
								cmdhiredis.Stdout = os.Stdout
								cmdhiredis.Stderr = os.Stderr
								if err := cmdhiredis.Run(); err == nil {
									pterm.DefaultBasicText.Println("hiredis 编译安装成功")
								} else {
									pterm.Error.Printfln("hiredis 编译安装失败:%v", err)
									return
								}
								if !checkldso() {
									mdstr = "echo '/usr/local/lib' >> /etc/ld.so.conf && ldconfig"
									cmd := exec.Command("sh", "-c", mdstr)
									cmd.Stdout = os.Stdout
									cmd.Stderr = os.Stderr
									if err := cmd.Run(); err == nil {
										pterm.DefaultBasicText.Println("hiredis 配置成功")
									} else {
										pterm.Error.Printfln("hiredis 配置失败:%v", err)
										return
									}
								}
								break
							}

						}

					} else {

						mdstr = "command -v " + bao
						cmdisinstall := exec.Command("sh", "-c", mdstr)
						if err := cmdisinstall.Run(); err == nil {
							continue
						} else {
							mdstr = "yum install -y " + bao
							cmd := exec.Command("sh", "-c", mdstr)
							cmd.Stdout = os.Stdout
							cmd.Stderr = os.Stderr
							err := cmd.Run()
							if err != nil {
								pterm.Error.Printfln("使用 yum 安装 Unbound 编译依赖 %v 失败:%v", bao, err)
								return
							}
						}
					}

				}

			} else if packageManager == "dnf" {
				baolist = []string{
					"gcc",
					"openssl-devel",
					"expat-devel",
					"libevent-devel",
					"make",
					"hiredis",
					"hiredis-devel",
				}
				for _, bao := range baolist {
					mdstr = "command -v " + bao
					cmdisinstall := exec.Command("sh", "-c", mdstr)
					cmdisinstall.Stdout = os.Stdout
					cmdisinstall.Stderr = os.Stderr
					if err := cmdisinstall.Run(); err == nil {
						continue
					} else {
						mdstr = "dnf install -y " + bao
						cmd := exec.Command("sh", "-c", mdstr)
						cmd.Stdout = os.Stdout
						cmd.Stderr = os.Stderr
						err := cmd.Run()
						if err != nil {
							pterm.Error.Printfln("使用 dnf 安装 Unbound 编译依赖 %v 失败:%v", bao, err)
							return
						}
					}
				}

			} else if packageManager == "zypper" {
				mdstr = "zypper install -t pattern -y devel_C_C++"
				cmd := exec.Command("sh", "-c", mdstr)
				cmd.Stdout = os.Stdout
				cmd.Stderr = os.Stderr
				err := cmd.Run()
				if err != nil {
					pterm.Error.Printfln("使用 zypper 安装 Unbound 开发工具和编译器失败:%v", err)
					return
				}
				mdstr = "zypper install -y libevent-devel openssl-devel libexpat-devel libuv-devel libhiredis-devel"
				cmd = exec.Command("sh", "-c", mdstr)
				cmd.Stdout = os.Stdout
				cmd.Stderr = os.Stderr
				err = cmd.Run()
				if err != nil {
					pterm.Error.Printfln("使用 zypper 安装 Unbound 必要的依赖包失败:%v", err)
					return
				}
			} else if packageManager == "pacman" {
				mdstr = "pacman -S -y base-devel libevent openssl expat libuv hiredis"
				cmd := exec.Command("sh", "-c", mdstr)
				cmd.Stdout = os.Stdout
				cmd.Stderr = os.Stderr
				err := cmd.Run()
				if err != nil {
					pterm.Error.Printfln("使用 pacman 安装 Unbound 编译依赖失败:%v", err)
					return
				}
			}
			pterm.DefaultBasicText.Println("Unbound 编译所需依赖安装完成")

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始安装 libevent")

			cmdislibevent := exec.Command("find", "/", "-name", "libevent-2.1.so.*")
			output, errislibevent := cmdislibevent.CombinedOutput()

			if errislibevent != nil {
				pterm.Error.Printfln("执行寻找 libevent-2.1.so.* 失败:%v", errislibevent)
				return
			}

			if strings.Contains(string(output), "libevent-2.1.so") {
				pterm.DefaultBasicText.Println("libevent 已经安装过了")
			} else {
				mdstr = "cd /root && wget https://oss.xlxbk.cn/libevent-2.1.12-stable.tar.gz && tar -zxvf libevent-2.1.12-stable.tar.gz && cd libevent-2.1.12-stable && ./configure && make && make install"
				cmdlibevent := exec.Command("sh", "-c", mdstr)
				cmdlibevent.Stdout = os.Stdout
				cmdlibevent.Stderr = os.Stderr
				errlibevent := cmdlibevent.Run()
				if errlibevent != nil {
					pterm.Error.Printfln("编译安装 libevent 失败:%v", errlibevent)
					return
				}
				pterm.DefaultBasicText.Println("libevent 安装完成")
			}

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始下载 Unbound 源代码")

			mdstr = "cd /root && wget https://nlnetlabs.nl/downloads/unbound/unbound-latest.tar.gz && tar -zxvf unbound-latest.tar.gz -C " + downloadpath
			cmd := exec.Command("sh", "-c", mdstr)
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			err := cmd.Run()
			if err != nil {
				pterm.Error.Printfln("下载/解压 Unbound 失败:%v", err)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 源代码下载完成")

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始编译 Unbound")

			filename := checkfilename()
			mdstr = "cd " + downloadpath + "/" + filename + " && ./configure --enable-subnet --with-libevent --with-libhiredis --enable-cachedb && make && make install"
			cmdinstall := exec.Command("sh", "-c", mdstr)
			cmdinstall.Stdout = os.Stdout
			cmdinstall.Stderr = os.Stderr
			errinstall := cmdinstall.Run()
			if errinstall != nil {
				pterm.Error.Printfln("编译安装 Unbound 失败:%v", errinstall)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 编译安装完成")

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始配置 Unbound")

			mdstr = "cd /usr/local/etc/unbound && wget -O root.hints https://www.internic.net/domain/named.root && touch unbound.log && chmod 666 unbound.log && rm -rf unbound.conf && wget https://oss.xlxbk.cn/unbound.conf && chmod 644 unbound.conf"
			cmdconf := exec.Command("sh", "-c", mdstr)
			cmdconf.Stdout = os.Stdout
			cmdconf.Stderr = os.Stderr
			errconf := cmdconf.Run()
			if errconf != nil {
				pterm.Error.Printfln("下载 Unbound 相关配置文件失败:%v", errconf)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 配置文件下载完成")

			mdstr = "chmod 777 /usr/local/etc/unbound"
			cmdchmod := exec.Command("sh", "-c", mdstr)
			cmdchmod.Stdout = os.Stdout
			cmdchmod.Stderr = os.Stderr
			errchmod := cmdchmod.Run()
			if errchmod != nil {
				pterm.Error.Printfln("赋予目录权限失败:%v", errchmod)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 配置文件赋予权限完成")

			mdstr = "unbound-anchor"
			cmdunbchor := exec.Command("sh", "-c", mdstr)
			cmdunbchor.Stdout = os.Stdout
			cmdunbchor.Stderr = os.Stderr
			errunbchor := cmdunbchor.Run()
			if errunbchor != nil {
				mdstr = "ls /usr/local/etc/unbound/root.key"
				cmdlsrootkey := exec.Command("sh", "-c", mdstr)
				cmdlsrootkey.Stdout = os.Stdout
				cmdlsrootkey.Stderr = os.Stderr
				errlsrootkey := cmdlsrootkey.Run()
				if errlsrootkey != nil {
					pterm.Error.Printfln("配置Unbound DNSSEC 失败:%v", errunbchor)
					return
				}
			}
			pterm.DefaultBasicText.Println("Unbound DNSSEC 配置完成")

			mdstr = "unbound-control-setup"
			cmdunbcoup := exec.Command("sh", "-c", mdstr)
			cmdunbcoup.Stdout = os.Stdout
			cmdunbcoup.Stderr = os.Stderr
			errunbcoup := cmdunbcoup.Run()
			if errunbcoup != nil {
				pterm.Error.Printfln("配置Unbound 远程控制失败:%v", errunbcoup)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 远程控制配置完成")

			if !checkUserExists("unbound") {
				mdstr = "groupadd unbound && useradd -m -g unbound -s /bin/false unbound"
				cmduser := exec.Command("sh", "-c", mdstr)
				cmduser.Stdout = os.Stdout
				cmduser.Stderr = os.Stderr
				erruser := cmduser.Run()
				if erruser != nil {
					pterm.Error.Printfln("创建 unbound 用户失败:%v", erruser)
					return
				}
				pterm.DefaultBasicText.Println("创建 unbound 用户完成")
			}

			mdstr = "cd /lib/systemd/system && wget https://oss.xlxbk.cn/unbound.service && chmod 644 unbound.service && systemctl daemon-reload && systemctl enable unbound"
			cmdserv := exec.Command("sh", "-c", mdstr)
			cmdserv.Stdout = os.Stdout
			cmdserv.Stderr = os.Stderr
			errserv := cmdserv.Run()
			if errserv != nil {
				pterm.Error.Printfln("配置 Unbound 服务失败:%v", errserv)
				return
			}
			pterm.DefaultBasicText.Println("Unbound 服务配置完成")

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始安装 redis")

			cmdisredis := exec.Command("sh", "-c", "command -v redis")
			cmdisredis.Stdout = os.Stdout
			cmdisredis.Stderr = os.Stderr
			errisredis := cmdisredis.Run()
			if errisredis == nil {
				pterm.DefaultBasicText.Println("redis 已经安装过了")
			} else {
				cmdredis := exec.Command(packageManager, "install", "-y", "redis")
				cmdredis.Stdout = os.Stdout
				cmdredis.Stderr = os.Stderr
				errredis := cmdredis.Run()
				if errredis != nil {
					pterm.Error.Printfln("安装 redis 失败:%v", err)
					return
				}
				pterm.DefaultBasicText.Println("redis 安装完成")
			}

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始安装 AdGuardHome")

			mdstr = "cd ~ && wget https://oss.xlxbk.cn/AdGuardHomeinstall.sh && chmod +x AdGuardHomeinstall.sh && ./AdGuardHomeinstall.sh"
			cmdadg := exec.Command("sh", "-c", mdstr)
			cmdadg.Stdout = os.Stdout
			cmdadg.Stderr = os.Stderr
			erradg := cmdadg.Run()
			if erradg != nil {
				pterm.Error.Printfln("安装 AdGuardHome 失败:%v", erradg)
				return
			}
			pterm.DefaultBasicText.Println("AdGuardHome 安装完成")

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始配置 AdGuardHome")

			resultname, _ := pterm.DefaultInteractiveTextInput.WithDefaultText("请输入用户名").Show()
			resultpwd, _ := pterm.DefaultInteractiveTextInput.WithDefaultText("请输入密码").Show()
			if resultname == "" || resultpwd == "" {
				pterm.Error.Printfln("用户名或密码不能为空")
				return
			}
			initLoginConfig(resultname, resultpwd)
			cook := getAdGuardHomeCookie(resultname, resultpwd)
			setconfone(cook)
			setconftwo(cook)
			list := getfiles(cook)
			if len(list) != 0 {
				for _, v := range list {
					delfiles(cook, v)
				}
			}

			mdstr = "systemctl start unbound"
			cmdstart := exec.Command("sh", "-c", mdstr)
			cmdstart.Stdout = os.Stdout
			cmdstart.Stderr = os.Stderr
			errstart := cmdstart.Run()
			if errstart != nil {
				pterm.Error.Printfln("启动 Unbound 服务失败:%v", errstart)
				return
			}

			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).WithStyle(pterm.NewStyle()).Println("Unbound 默认目录 /usr/local/etc/unbound 配置文件、日志什么的都在这个目录有特殊需求可以自行更改配置文件")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("Unbound 监听端口 5363")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("Unbound 监听IP 所有IP")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("使用 lsof -i:5363 可以检测Unbound是否启动成功")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("如果启动失败,请运行 systemctl status unbound 截图发送给开发者")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println("AdGuardHome 管理界面地址:http://你的公网ip:9000")
			pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgRed)).Println(fmt.Sprintf("AdGuardHome 账号:%s 密码:%s", resultname, resultpwd))

		}

	case "2 升级Unbound":
		var mdstr string
		result, _ := pterm.DefaultInteractiveConfirm.WithDefaultText("选择y会删除 /root 目录下 unbound 相关文件和文件夹").WithTextStyle(pterm.NewStyle(pterm.FgYellow)).Show()
		if result {
			mdstr = "cd /root && rm -rf unbound*"
			cmd := exec.Command("sh", "-c", mdstr)
			err := cmd.Run()
			if err != nil {
				pterm.Error.Printfln("删除 unbound 相关文件以及文件夹失败:%v", err)
				return
			}
		}

		mdstr = "mkdir -p " + downloadpath
		cmdmkdir := exec.Command("sh", "-c", mdstr)
		errmkdir := cmdmkdir.Run()
		if errmkdir != nil {
			pterm.Error.Printfln("创建 /root/unbound 目录失败:%v", errmkdir)
			return
		}

		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始下载 Unbound 源代码")

		mdstr = "cd /root && wget https://pure.xlxbk.cn/nlnetlabs/downloads/unbound/unbound-latest.tar.gz && tar -zxvf unbound-latest.tar.gz -C " + downloadpath
		cmd := exec.Command("sh", "-c", mdstr)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err := cmd.Run()
		if err != nil {
			pterm.Error.Printfln("下载/解压 Unbound 失败:%v", err)
			return
		}
		pterm.DefaultBasicText.Println("Unbound 源代码下载完成")

		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("开始编译 Unbound")

		filename := checkfilename()
		mdstr = "cd " + downloadpath + "/" + filename + " && ./configure --enable-subnet --with-libevent --with-libhiredis --enable-cachedb && make && make install"
		cmdinstall := exec.Command("sh", "-c", mdstr)
		cmdinstall.Stdout = os.Stdout
		cmdinstall.Stderr = os.Stderr
		errinstall := cmdinstall.Run()
		if errinstall != nil {
			pterm.Error.Printfln("编译安装 Unbound 失败:%v", errinstall)
			return
		}
		pterm.DefaultBasicText.Println("Unbound 编译安装完成")

		mdstr = "systemctl restart unbound"
		cmdstart := exec.Command("sh", "-c", mdstr)
		cmdstart.Stdout = os.Stdout
		cmdstart.Stderr = os.Stderr
		errstart := cmdstart.Run()
		if errstart != nil {
			pterm.Error.Printfln("重新启动 Unbound 服务失败:%v", errstart)
			return
		}
		pterm.DefaultBasicText.WithStyle(pterm.NewStyle(pterm.FgGreen)).Println("Unbound 升级完成")
	}
}

func checkUserExists(username string) bool {
	file, err := os.Open("/etc/passwd")
	if err != nil {
		pterm.Error.Printfln("打开/etc/passwd文件失败:%v", err)
		return false
	}
	defer func(file *os.File) {
		err = file.Close()
		if err != nil {
			pterm.Error.Printfln("关闭/etc/passwd文件失败:%v", err)
		}
	}(file)

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		fields := strings.Split(line, ":")
		if len(fields) > 0 && fields[0] == username {
			return true
		}
	}

	if err := scanner.Err(); err != nil {
		pterm.Error.Printfln("读取/etc/passwd文件失败:%v", err)
	}
	return false
}

func checkfilename() string {

	entries, _ := os.ReadDir(downloadpath)
	for _, entry := range entries {
		if strings.Contains(entry.Name(), "unbound") {
			return entry.Name()
		}
	}
	return ""
}

func checkldso() bool {
	file, err := os.Open("/etc/ld.so.conf")
	if err != nil {
		pterm.Error.Printfln("打开 /etc/ld.so.conf 文件失败:%v", err)
		return false
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		if strings.Contains(line, "/usr/local/lib") {
			return true
		}
	}
	return false
}

func initLoginConfig(name string, pwd string) {
	url := "http://127.0.0.1:3000/control/install/configure"
	method := "POST"

	payload := strings.NewReader(fmt.Sprintf(`{"web":{"ip":"0.0.0.0","port":9000,"status":"","can_autofix":false},"dns":{"ip":"0.0.0.0","port":5353,"status":"","can_autofix":false},"username":"%s","password":"%s"}`, name, pwd))

	client := &http.Client{}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		pterm.Error.Printfln("请求失败:%v", err)
		return
	}
	req.Header.Add("Accept", "application/json, text/plain, */*")
	req.Header.Add("Accept-Language", "zh-CN,zh;q=0.9")
	req.Header.Add("Cache-Control", "no-cache")
	req.Header.Add("Pragma", "no-cache")
	req.Header.Add("Proxy-Connection", "keep-alive")
	req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36")
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Connection", "keep-alive")

	res, err := client.Do(req)
	if err != nil {
		pterm.Error.Printfln("初始化设置 AdGuardHome 失败:%v", err)
		return
	}
	defer func(Body io.ReadCloser) {
		err = Body.Close()
		if err != nil {
			pterm.Error.Printfln("关闭 Body 失败:%v", err)
		}
	}(res.Body)
}

func getAdGuardHomeCookie(name string, pwd string) string {
	url := "http://127.0.0.1:9000/control/login"
	method := "POST"

	payload := strings.NewReader(fmt.Sprintf(`{"name":"%s","password":"%s"}`, name, pwd))

	client := &http.Client{}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		pterm.Error.Printfln("请求失败:%v", err)
		return ""
	}
	req.Header.Add("Accept", "application/json, text/plain, */*")
	req.Header.Add("Accept-Language", "zh-CN,zh;q=0.9")
	req.Header.Add("Cache-Control", "no-cache")
	req.Header.Add("Pragma", "no-cache")
	req.Header.Add("Proxy-Connection", "keep-alive")
	req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36")
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Connection", "keep-alive")

	res, err := client.Do(req)
	if err != nil {
		pterm.Error.Printfln("获取 AdGuardHome Cookie 失败:%v", err)
		return ""
	}
	defer func(Body io.ReadCloser) {
		err = Body.Close()
		if err != nil {
			pterm.Error.Printfln("关闭 Body 失败:%v", err)
		}
	}(res.Body)

	return res.Cookies()[0].Name + "=" + res.Cookies()[0].Value
}

func setconfone(cook string) {
	url := "http://127.0.0.1:9000/control/dns_config"
	method := "POST"

	payload := strings.NewReader(`{"fallback_dns":[],"bootstrap_dns":["127.0.0.1:5363","tcp://127.0.0.1:5363"],"upstream_mode":"parallel","resolve_clients":true,"local_ptr_upstreams":[],"use_private_ptr_resolvers":true,"upstream_dns":["127.0.0.1:5363","tcp://127.0.0.1:5363"]}`)

	client := &http.Client{}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		pterm.Error.Printfln("请求失败:%v", err)
		return
	}
	req.Header.Add("Accept", "application/json, text/plain, */*")
	req.Header.Add("Accept-Language", "zh-CN,zh;q=0.9")
	req.Header.Add("Cache-Control", "no-cache")
	req.Header.Add("Pragma", "no-cache")
	req.Header.Add("Proxy-Connection", "keep-alive")
	req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36")
	req.Header.Add("Cookie", cook)
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Connection", "keep-alive")

	res, err := client.Do(req)
	if err != nil {
		pterm.Error.Printfln("配置 AdGuardHome 失败:%v", err)
		return
	}
	defer func(Body io.ReadCloser) {
		err = Body.Close()
		if err != nil {
			pterm.Error.Printfln("关闭 Body 失败:%v", err)
		}
	}(res.Body)

}
func setconftwo(cook string) {
	url := "http://127.0.0.1:9000/control/dns_config"
	method := "POST"

	payload := strings.NewReader(`{"ratelimit":0,"ratelimit_subnet_len_ipv4":24,"ratelimit_subnet_len_ipv6":56,"ratelimit_whitelist":[],"blocking_mode":"nxdomain","blocking_ipv4":"0.0.0.0","blocking_ipv6":"::","blocked_response_ttl":10,"edns_cs_enabled":true,"disable_ipv6":false,"dnssec_enabled":true,"edns_cs_use_custom":false,"edns_cs_custom_ip":""}`)

	client := &http.Client{}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		pterm.Error.Printfln("请求失败:%v", err)
		return
	}
	req.Header.Add("Accept", "application/json, text/plain, */*")
	req.Header.Add("Accept-Language", "zh-CN,zh;q=0.9")
	req.Header.Add("Cache-Control", "no-cache")
	req.Header.Add("Pragma", "no-cache")
	req.Header.Add("Proxy-Connection", "keep-alive")
	req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36")
	req.Header.Add("Cookie", cook)
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Connection", "keep-alive")

	res, err := client.Do(req)
	if err != nil {
		pterm.Error.Printfln("配置 AdGuardHome 失败:%v", err)
		return
	}
	defer func(Body io.ReadCloser) {
		err = Body.Close()
		if err != nil {
			pterm.Error.Printfln("关闭 Body 失败:%v", err)
		}
	}(res.Body)

}

func getfiles(cook string) []string {
	var list []string
	url := "http://127.0.0.1:9000/control/filtering/status"
	method := "GET"

	client := &http.Client{}
	req, err := http.NewRequest(method, url, nil)

	if err != nil {
		pterm.Error.Printfln("请求失败:%v", err)
		return list
	}
	req.Header.Add("Accept", "application/json, text/plain, */*")
	req.Header.Add("Accept-Language", "zh-CN,zh;q=0.9")
	req.Header.Add("Cache-Control", "no-cache")
	req.Header.Add("Pragma", "no-cache")
	req.Header.Add("Proxy-Connection", "keep-alive")
	req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36")
	req.Header.Add("Cookie", cook)
	req.Header.Add("Connection", "keep-alive")

	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return list
	}
	defer func(Body io.ReadCloser) {
		err = Body.Close()
		if err != nil {
			pterm.Error.Printfln("关闭 Body 失败:%v", err)
		}
	}(res.Body)

	body, err := io.ReadAll(res.Body)
	if err != nil {
		pterm.Error.Printfln("获取 AdGuardHome 过滤列表失败:%v", err)
		return list
	}
	var p fastjson.Parser
	jsonda, _ := p.ParseBytes(body)
	listtump := jsonda.GetArray("filters")

	if len(listtump) == 0 {
		return list
	} else {
		for _, v := range listtump {
			list = append(list, string(v.GetStringBytes("url")))
		}
	}
	return list
}

func delfiles(cook string, liststring string) {
	url := "http://127.0.0.1:9000/control/filtering/remove_url"
	method := "POST"

	payload := strings.NewReader(fmt.Sprintf(`{"url":"%s","whitelist":false}`, liststring))

	client := &http.Client{}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		pterm.Error.Printfln("请求失败:%v", err)
		return
	}
	req.Header.Add("Accept", "application/json, text/plain, */*")
	req.Header.Add("Accept-Language", "zh-CN,zh;q=0.9")
	req.Header.Add("Cache-Control", "no-cache")
	req.Header.Add("Pragma", "no-cache")
	req.Header.Add("Proxy-Connection", "keep-alive")
	req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36")
	req.Header.Add("Cookie", cook)
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Connection", "keep-alive")

	res, err := client.Do(req)
	if err != nil {
		pterm.Error.Printfln("删除 AdGuardHome 过滤列表失败:%v", err)
		return
	}
	defer func(Body io.ReadCloser) {
		err = Body.Close()
		if err != nil {
			pterm.Error.Printfln("关闭 Body 失败:%v", err)
		}
	}(res.Body)

}

这个脚本会有几个地方要确认,按照提示确认即可,理论上兼容所有linux系统,目前只测试了Debian、Ubuntu、RockyLinux这三个

wget https://oss.xlxbk.cn/unbound/linux_amd64/V1.0.0/installunbound && chmod +x installunbound && ./installunbound
wget https://oss.xlxbk.cn/unbound/linux_amd64/V1.0.1/installunbound && chmod +x installunbound && ./installunbound

有问题截图发评论区,看到了就会回复

更新历史
  • V1.0.0_2024-06-15 初代版本发布
  • V1.0.1_2024-07-10 增加AdGuardHome安装
© 版权声明
THE END
喜欢就支持一下吧
点赞9赞赏 分享
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容