hostSync/cmd/list.go

270 lines
6.5 KiB
Go

package cmd
import (
"fmt"
"os"
"sort"
"github.com/evil7/hostsync/core"
"github.com/evil7/hostsync/utils"
"github.com/spf13/cobra"
)
var (
rawOutput bool
)
// listCmd 列表命令
var listCmd = &cobra.Command{
Use: "list [blockName]",
Short: "查看 Hosts 配置",
Long: `查看 Hosts 配置,可以列出所有块或指定块的配置。
示例:
hostsync list # 列出所有块配置
hostsync list github # 列出指定块配置
hostsync list --raw # 原始格式输出,便于导出`,
Run: runList,
}
func init() {
listCmd.Flags().BoolVar(&rawOutput, "raw", false, "原始格式输出")
}
func runList(cmd *cobra.Command, args []string) {
hm := core.NewHostsManager()
if err := hm.Load(); err != nil {
utils.LogError("加载hosts文件失败: %v", err)
os.Exit(1)
}
if len(args) == 0 {
// 列出所有块
listAllBlocks(hm)
} else {
// 列出指定块
blockName := args[0]
listBlock(hm, blockName)
}
}
func listAllBlocks(hm *core.HostsManager) {
if len(hm.Blocks) == 0 {
utils.LogInfo("没有找到任何配置块")
return
}
if rawOutput {
// 获取排序后的块名称列表用于原始输出
var blockNames []string
for name := range hm.Blocks {
blockNames = append(blockNames, name)
}
sort.Strings(blockNames)
// 原始格式输出
for _, name := range blockNames {
block := hm.Blocks[name]
utils.LogResult("# %s:\n", name)
for _, entry := range block.Entries {
prefix := ""
if !entry.Enabled {
prefix = "# "
}
if entry.Comment != "" {
utils.LogResult("%s%-16s %s # %s\n", prefix, entry.IP, entry.Domain, entry.Comment)
} else {
utils.LogResult("%s%-16s %s\n", prefix, entry.IP, entry.Domain)
}
}
if block.DNS != "" {
utils.LogResult("# useDns: %s\n", block.DNS)
}
if block.DoH != "" {
utils.LogResult("# useDoh: %s\n", block.DoH)
}
if block.Server != "" {
utils.LogResult("# useSrv: %s\n", block.Server)
}
if block.CronJob != "" {
utils.LogResult("# cronJob: %s\n", block.CronJob)
}
if !block.UpdateAt.IsZero() {
utils.LogResult("# updateAt: %s\n", block.UpdateAt.Format("2006-01-02 15:04:05"))
}
utils.LogResult("# %s;\n\n", name)
}
return
}
// 表格格式输出
headers := []string{"块名称", "状态", "条目数", "DNS配置", "最后更新"}
var rows [][]string
// 获取排序后的块名称列表
var blockNames []string
for name := range hm.Blocks {
blockNames = append(blockNames, name)
}
sort.Strings(blockNames)
for _, name := range blockNames {
block := hm.Blocks[name]
// 计算启用的条目数
enabledCount := 0
for _, entry := range block.Entries {
if entry.Enabled {
enabledCount++
}
}
// 根据块状态和条目状态确定显示状态
var status string
if len(block.Entries) == 0 {
status = "空块"
} else if enabledCount == 0 {
status = "全部禁用"
} else if enabledCount == len(block.Entries) {
status = "全部启用"
} else {
status = "部分启用"
}
entryInfo := fmt.Sprintf("%d/%d", enabledCount, len(block.Entries))
dnsConfig := ""
if block.DNS != "" {
dnsConfig = fmt.Sprintf("DNS: %s", block.DNS)
} else if block.DoH != "" {
dnsConfig = fmt.Sprintf("DoH: %s", utils.TruncateWithWidth(block.DoH, 30))
} else if block.Server != "" {
dnsConfig = fmt.Sprintf("服务器: %s", block.Server)
} else {
dnsConfig = "系统默认"
}
updateTime := "从未更新"
if !block.UpdateAt.IsZero() {
updateTime = block.UpdateAt.Format("2006-01-02 15:04")
}
rows = append(rows, []string{name, status, entryInfo, dnsConfig, updateTime})
}
utils.LogInfo("Hosts 配置块列表 (%d 个块)\n", len(hm.Blocks))
// 设置合适的列宽
columnWidths := []int{12, 12, 8, 35, 17}
utils.FormatTable(headers, rows, columnWidths)
}
func listBlock(hm *core.HostsManager, blockName string) {
block := hm.GetBlock(blockName)
if block == nil {
utils.LogError("块不存在: %s", blockName)
os.Exit(1)
}
if rawOutput {
// 原始格式输出
fmt.Printf("# %s:\n", blockName)
for _, entry := range block.Entries {
prefix := ""
if !entry.Enabled {
prefix = "# "
}
if entry.Comment != "" {
fmt.Printf("%s%-16s %s # %s\n", prefix, entry.IP, entry.Domain, entry.Comment)
} else {
fmt.Printf("%s%-16s %s\n", prefix, entry.IP, entry.Domain)
}
}
if block.DNS != "" {
fmt.Printf("# useDns: %s\n", block.DNS)
}
if block.DoH != "" {
fmt.Printf("# useDoh: %s\n", block.DoH)
}
if block.Server != "" {
fmt.Printf("# useSrv: %s\n", block.Server)
}
if block.CronJob != "" {
fmt.Printf("# cronJob: %s\n", block.CronJob)
}
if !block.UpdateAt.IsZero() {
fmt.Printf("# updateAt: %s\n", block.UpdateAt.Format("2006-01-02 15:04:05"))
}
fmt.Printf("# %s;\n", blockName)
return
}
// 计算启用的条目数
enabledCount := 0
for _, entry := range block.Entries {
if entry.Enabled {
enabledCount++
}
}
// 详细信息显示
fmt.Printf("名称: %s\n", blockName)
// 根据块状态和条目状态确定显示状态
if !block.Enabled {
fmt.Printf("状态: 禁用\n")
} else if len(block.Entries) == 0 {
fmt.Printf("状态: 空块\n")
} else if enabledCount == 0 {
fmt.Printf("状态: 全部禁用 (0/%d)\n", len(block.Entries))
} else if enabledCount == len(block.Entries) {
fmt.Printf("状态: 全部启用 (%d/%d)\n", enabledCount, len(block.Entries))
} else {
fmt.Printf("状态: 部分启用 (%d/%d)\n", enabledCount, len(block.Entries))
}
if block.DNS != "" {
fmt.Printf("DNS服务器: %s\n", block.DNS)
}
if block.DoH != "" {
fmt.Printf("DoH服务器: %s\n", block.DoH)
}
if block.Server != "" {
fmt.Printf("预设服务器: %s\n", block.Server)
}
if block.CronJob != "" {
fmt.Printf("定时任务: %s\n", block.CronJob)
}
if !block.UpdateAt.IsZero() {
fmt.Printf("最后更新: %s\n", block.UpdateAt.Format("2006-01-02 15:04:05"))
}
if len(block.Entries) == 0 {
utils.LogInfo("\n没有域名记录")
return
}
utils.LogInfo("\n域名记录 (%d 个条目):\n", len(block.Entries))
// 域名记录表格
headers := []string{"状态", "IP地址", "域名", "备注"}
var rows [][]string
for _, entry := range block.Entries {
status := "启用"
if !entry.Enabled {
status = "禁用"
}
comment := entry.Comment
if comment == "" {
comment = "-"
}
rows = append(rows, []string{status, entry.IP, entry.Domain, comment})
}
// 设置合适的列宽
columnWidths := []int{8, 16, 30, 20}
utils.FormatTable(headers, rows, columnWidths)
}