Skip to content

Commit

Permalink
Merge pull request #42 from icpd/41-nodeonly
Browse files Browse the repository at this point in the history
feat: support nodeonly & ignore sublink failed
  • Loading branch information
icpd committed Jun 18, 2023
2 parents cd80e6d + 6ff1e5f commit d213ab3
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 26 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,15 @@ Clash配置转换,默认自动获取[ACL4SSR](https://github.com/ACL4SSR/ACL4S

# 通过订阅链接
./subscribe2clash --link=subscribe_link -o=output_file

# 只输出节点信息
./subscribe2clash --link=subscribe_link -o=output_file --nodeonly
```


### web服务
启动一个 HTTP 服务,访问 http://localhost:8162/?link=你的订阅链接 即可获取 Clash 配置。
只输出节点信息 http://localhost:8162/?nodeonly=1&link=你的订阅链接
```bash
./subscribe2clash
```
Expand Down Expand Up @@ -94,7 +98,6 @@ Clash配置转换,默认自动获取[ACL4SSR](https://github.com/ACL4SSR/ACL4S
./subscribe2clash -t 6
```





4 changes: 3 additions & 1 deletion app/api/clash.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/gin-gonic/gin"
"github.com/icpd/subscribe2clash/internal/clash"
"github.com/spf13/cast"
)

const key = "link"
Expand All @@ -23,7 +24,8 @@ func (cc *ClashController) Clash(c *gin.Context) {
return
}

config, err := clash.Config(clash.Url, links)
nodeOnly, _ := c.GetQuery("nodeonly")
config, err := clash.Config(clash.Url, links, cast.ToBool(nodeOnly))
if err != nil {
c.String(http.StatusInternalServerError, err.Error())
c.Abort()
Expand Down
30 changes: 28 additions & 2 deletions boot/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,32 @@ func generateConfig() {
options := Options()
g := acl.New(options...)

if global.NodeOnly {
var config string
var err error
switch {
case global.SourceFile != "":
config, err = clash.Config(clash.File, global.SourceFile, true)
case global.SourceLinks != "":
config, err = clash.Config(clash.Url, global.SourceLinks, true)
default:
return
}

if err != nil {
log.Fatal("生成配置文件内容失败", err)
}

// 写入配置文件
err = os.WriteFile(global.OutputFile, []byte(config), 0644)
if err != nil {
log.Fatal("写入配置文件失败", err)
}

os.Exit(0)
return
}

var wg sync.WaitGroup
wg.Add(1)

Expand All @@ -36,9 +62,9 @@ func generateConfig() {
var err error
switch {
case global.SourceFile != "":
config, err = clash.Config(clash.File, global.SourceFile)
config, err = clash.Config(clash.File, global.SourceFile, false)
case global.SourceLinks != "":
config, err = clash.Config(clash.Url, global.SourceLinks)
config, err = clash.Config(clash.Url, global.SourceLinks, false)
default:
return
}
Expand Down
1 change: 1 addition & 0 deletions boot/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func init() {
flag.StringVar(&req.Proxy, "proxy", "", "http代理")
flag.IntVar(&global.Tick, "t", 6, "规则更新频率(小时)")
flag.BoolVar(&global.Version, "version", false, "查看版本信息")
flag.BoolVar(&global.NodeOnly, "nodeonly", false, "只生成节点信息")
flag.StringVar(&global.SourceLinks, "link", "", "订阅链接")
flag.StringVar(&global.SourceFile, "file", "", "订阅文件")
flag.Parse()
Expand Down
4 changes: 2 additions & 2 deletions internal/clash/clash.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const (
File
)

func Config(sourceType SourceType, source string) (string, error) {
func Config(sourceType SourceType, source string, nodeOnly bool) (string, error) {
var contents []string
var err error

Expand All @@ -39,7 +39,7 @@ func Config(sourceType SourceType, source string) (string, error) {
}

proxies := subscribe.ParseProxy(contents)
config, err := subscribe.GenerateClashConfig(proxies)
config, err := subscribe.GenerateClashConfig(proxies, nodeOnly)
if err != nil {
return "", err
}
Expand Down
1 change: 1 addition & 0 deletions internal/global/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var (
Listen string
Tick int
Version bool
NodeOnly bool

SourceLinks string
SourceFile string
Expand Down
62 changes: 44 additions & 18 deletions internal/subscribe/generate_clash_yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,39 @@ import (
)

func (c *Clash) LoadTemplate() []byte {
_, err := os.Stat(c.path)
if err != nil && os.IsNotExist(err) {
log.Printf("[%s] template doesn't exist. err: %v", c.path, err)
return nil
}
buf, err := os.ReadFile(c.path)
if err != nil {
log.Printf("[%s] template open the failure. err: %v", c.path, err)
return nil
}
err = yaml.Unmarshal(buf, &c)
if err != nil {
log.Printf("[%s] Template format error. err: %v", c.path, err)
if !c.NodeOnly() {
_, err := os.Stat(c.path)
if err != nil && os.IsNotExist(err) {
log.Printf("[%s] template doesn't exist. err: %v", c.path, err)
return nil
}
buf, err := os.ReadFile(c.path)
if err != nil {
log.Printf("[%s] template open the failure. err: %v", c.path, err)
return nil
}
err = yaml.Unmarshal(buf, &c)
if err != nil {
log.Printf("[%s] Template format error. err: %v", c.path, err)
}
}

var proxiesName []string
names := map[string]int{}

for _, proto := range c.rawProxies {

proxy := make(map[string]any)
j, _ := json.Marshal(proto)
_ = json.Unmarshal(j, &proxy)
p, ok := proto.(map[string]any)
if ok {
proxy = p
} else {
j, err := json.Marshal(proto)
if err != nil {
log.Printf("json marshal error: %v", err)
continue
}
_ = json.Unmarshal(j, &proxy)
}

var name string
switch reflect.TypeOf(proto).Kind() {
Expand Down Expand Up @@ -81,18 +91,34 @@ func (c *Clash) LoadTemplate() []byte {

}

d, err := yaml.Marshal(c)
var yamlOut any = c
if c.NodeOnly() {
type nodeOnly struct {
Proxies []map[string]any `yaml:"proxies"`
}

yamlOut = nodeOnly{
Proxies: c.Proxies,
}
}

d, err := yaml.Marshal(yamlOut)
if err != nil {
return nil
}

return d
}

func GenerateClashConfig(proxies []any) ([]byte, error) {
func (c *Clash) NodeOnly() bool {
return c.nodeOnly
}

func GenerateClashConfig(proxies []any, nodeOnly bool) ([]byte, error) {
clash := Clash{
path: acl.GlobalGen.OutputFile,
rawProxies: proxies,
nodeOnly: nodeOnly,
}

r := clash.LoadTemplate()
Expand Down
2 changes: 1 addition & 1 deletion internal/subscribe/parse_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func ParseProxy(contentSlice []string) []any {
// try unmarshal clash config
var c Clash
if err := yaml.Unmarshal([]byte(v), &c); err == nil {
for _, pg := range c.ProxyGroups {
for _, pg := range c.Proxies {
proxies = append(proxies, pg)
}
continue
Expand Down
1 change: 1 addition & 0 deletions internal/subscribe/proxy_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ type Clash struct {

path string
rawProxies []any
nodeOnly bool
}

type Trojan struct {
Expand Down
3 changes: 2 additions & 1 deletion internal/subscribe/req.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ func GetRawProxiesFromLinks(links string) ([]string, error) {
for _, link := range subLinks {
content, err := req.HttpGet(link)
if err != nil {
return nil, err
log.Printf("Warning: 获取 %s 内容失败, err:%v", link, err)
continue
}

rawProxiesSlice = append(rawProxiesSlice, ParseRawProxies(content))
Expand Down

0 comments on commit d213ab3

Please sign in to comment.