mirror of
https://github.com/bolucat/Archive.git
synced 2025-09-26 20:21:35 +08:00
Update On Thu Jul 4 20:30:58 CEST 2024
This commit is contained in:
@@ -194,6 +194,7 @@ These two concepts are notable: `input` and `output`. The `input` is the data so
|
||||
支持的 `input` 输入格式:
|
||||
|
||||
- **text**:纯文本 IP 和 CIDR(例如:`1.1.1.1` 或 `1.0.0.0/24`)
|
||||
- **stdin**:从 standard input 获取纯文本 IP 和 CIDR(例如:`1.1.1.1` 或 `1.0.0.0/24`)
|
||||
- **private**:局域网和私有网络 CIDR(例如:`192.168.0.0/16` 和 `127.0.0.0/8`)
|
||||
- **cutter**:用于裁剪前置步骤中的数据
|
||||
- **v2rayGeoIPDat**:V2Ray GeoIP dat 格式(`geoip.dat`)
|
||||
@@ -207,6 +208,7 @@ These two concepts are notable: `input` and `output`. The `input` is the data so
|
||||
支持的 `output` 输出格式:
|
||||
|
||||
- **text**:纯文本 CIDR(例如:`1.0.0.0/24`)
|
||||
- **stdout**:将纯文本 CIDR 输出到 standard output(例如:`1.0.0.0/24`)
|
||||
- **v2rayGeoIPDat**:V2Ray GeoIP dat 格式(`geoip.dat`,适用于 [V2Ray](https://github.com/v2fly/v2ray-core)、[Xray-core](https://github.com/XTLS/Xray-core) 和 [Trojan-Go](https://github.com/p4gefau1t/trojan-go))
|
||||
- **maxmindMMDB**:MaxMind mmdb 数据格式(`GeoLite2-Country.mmdb`,适用于 [Clash](https://github.com/Dreamacro/clash) 和 [Leaf](https://github.com/eycorsican/leaf))
|
||||
- **singboxSRS**:sing-box SRS 格式(`geoip-cn.srs`,适用于 [sing-box](https://github.com/SagerNet/sing-box))
|
||||
@@ -261,6 +263,7 @@ All available input formats:
|
||||
- maxmindGeoLite2CountryCSV (Convert MaxMind GeoLite2 country CSV data to other formats)
|
||||
- singboxSRS (Convert sing-box SRS data to other formats)
|
||||
- private (Convert LAN and private network CIDR to other formats)
|
||||
- stdin (Accept plaintext IP & CIDR from standard input, separated by newline)
|
||||
- text (Convert plaintext IP & CIDR to other formats)
|
||||
- clashRuleSetClassical (Convert classical type of Clash RuleSet to other formats (just processing IP & CIDR lines))
|
||||
- clashRuleSet (Convert ipcidr type of Clash RuleSet to other formats)
|
||||
@@ -275,6 +278,7 @@ All available output formats:
|
||||
- clashRuleSet (Convert data to ipcidr type of Clash RuleSet)
|
||||
- surgeRuleSet (Convert data to Surge RuleSet)
|
||||
- text (Convert data to plaintext CIDR format)
|
||||
- stdout (Convert data to plaintext CIDR format and output to standard output)
|
||||
```
|
||||
|
||||
## License
|
||||
|
@@ -122,6 +122,29 @@
|
||||
"onlyIPType": "ipv4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "stdin",
|
||||
"action": "add",
|
||||
"args": {
|
||||
"name": "cn"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "stdin",
|
||||
"action": "add",
|
||||
"args": {
|
||||
"name": "cn",
|
||||
"onlyIPType": "ipv4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "stdin",
|
||||
"action": "remove",
|
||||
"args": {
|
||||
"name": "cn",
|
||||
"onlyIPType": "ipv6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "private",
|
||||
"action": "add"
|
||||
@@ -220,6 +243,32 @@
|
||||
"onlyIPType": "ipv6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "stdout",
|
||||
"action": "output"
|
||||
},
|
||||
{
|
||||
"type": "stdout",
|
||||
"action": "output",
|
||||
"args": {
|
||||
"wantedList": ["cn", "us", "private"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "stdout",
|
||||
"action": "output",
|
||||
"args": {
|
||||
"onlyIPType": "ipv6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "stdout",
|
||||
"action": "output",
|
||||
"args": {
|
||||
"wantedList": ["cn", "us", "private"],
|
||||
"onlyIPType": "ipv6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "clashRuleSetClassical",
|
||||
"action": "output",
|
||||
|
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -14,8 +15,13 @@ var (
|
||||
|
||||
func ListInputConverter() {
|
||||
fmt.Println("All available input formats:")
|
||||
for name, ic := range inputConverterMap {
|
||||
fmt.Printf(" - %s (%s)\n", name, ic.GetDescription())
|
||||
keys := make([]string, 0, len(inputConverterMap))
|
||||
for name := range inputConverterMap {
|
||||
keys = append(keys, name)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, name := range keys {
|
||||
fmt.Printf(" - %s (%s)\n", name, inputConverterMap[name].GetDescription())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +36,13 @@ func RegisterInputConverter(name string, c InputConverter) error {
|
||||
|
||||
func ListOutputConverter() {
|
||||
fmt.Println("All available output formats:")
|
||||
for name, oc := range outputConverterMap {
|
||||
fmt.Printf(" - %s (%s)\n", name, oc.GetDescription())
|
||||
keys := make([]string, 0, len(outputConverterMap))
|
||||
for name := range outputConverterMap {
|
||||
keys = append(keys, name)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, name := range keys {
|
||||
fmt.Printf(" - %s (%s)\n", name, outputConverterMap[name].GetDescription())
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -85,7 +85,7 @@ func (g *maxmindMMDBIn) Input(container lib.Container) (lib.Container, error) {
|
||||
var fd io.ReadCloser
|
||||
var err error
|
||||
switch {
|
||||
case strings.HasPrefix(g.URI, "http://"), strings.HasPrefix(g.URI, "https://"):
|
||||
case strings.HasPrefix(strings.ToLower(g.URI), "http://"), strings.HasPrefix(strings.ToLower(g.URI), "https://"):
|
||||
fd, err = g.downloadFile(g.URI)
|
||||
default:
|
||||
fd, err = os.Open(g.URI)
|
||||
|
@@ -84,7 +84,7 @@ func (t *textIn) Input(container lib.Container) (lib.Container, error) {
|
||||
err = t.walkDir(t.InputDir, entries)
|
||||
case t.Name != "" && t.URI != "":
|
||||
switch {
|
||||
case strings.HasPrefix(t.URI, "http://"), strings.HasPrefix(t.URI, "https://"):
|
||||
case strings.HasPrefix(strings.ToLower(t.URI), "http://"), strings.HasPrefix(strings.ToLower(t.URI), "https://"):
|
||||
err = t.walkRemoteFile(t.URI, t.Name, entries)
|
||||
default:
|
||||
err = t.walkLocalFile(t.URI, t.Name, entries)
|
||||
|
@@ -92,7 +92,7 @@ func (s *srsIn) Input(container lib.Container) (lib.Container, error) {
|
||||
err = s.walkDir(s.InputDir, entries)
|
||||
case s.Name != "" && s.URI != "":
|
||||
switch {
|
||||
case strings.HasPrefix(s.URI, "http://"), strings.HasPrefix(s.URI, "https://"):
|
||||
case strings.HasPrefix(strings.ToLower(s.URI), "http://"), strings.HasPrefix(strings.ToLower(s.URI), "https://"):
|
||||
err = s.walkRemoteFile(s.URI, s.Name, entries)
|
||||
default:
|
||||
err = s.walkLocalFile(s.URI, s.Name, entries)
|
||||
|
113
geoip/plugin/special/stdin.go
Normal file
113
geoip/plugin/special/stdin.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package special
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/Loyalsoldier/geoip/lib"
|
||||
)
|
||||
|
||||
const (
|
||||
typeStdin = "stdin"
|
||||
descStdin = "Accept plaintext IP & CIDR from standard input, separated by newline"
|
||||
)
|
||||
|
||||
func init() {
|
||||
lib.RegisterInputConfigCreator(typeStdin, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
||||
return newStdin(action, data)
|
||||
})
|
||||
lib.RegisterInputConverter(typeStdin, &stdin{
|
||||
Description: descStdin,
|
||||
})
|
||||
}
|
||||
|
||||
func newStdin(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
||||
var tmp struct {
|
||||
Name string `json:"name"`
|
||||
OnlyIPType lib.IPType `json:"onlyIPType"`
|
||||
}
|
||||
|
||||
if len(data) > 0 {
|
||||
if err := json.Unmarshal(data, &tmp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &stdin{
|
||||
Type: typeStdin,
|
||||
Action: action,
|
||||
Description: descStdin,
|
||||
Name: tmp.Name,
|
||||
OnlyIPType: tmp.OnlyIPType,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type stdin struct {
|
||||
Type string
|
||||
Action lib.Action
|
||||
Description string
|
||||
Name string
|
||||
OnlyIPType lib.IPType
|
||||
}
|
||||
|
||||
func (s *stdin) GetType() string {
|
||||
return s.Type
|
||||
}
|
||||
|
||||
func (s *stdin) GetAction() lib.Action {
|
||||
return s.Action
|
||||
}
|
||||
|
||||
func (s *stdin) GetDescription() string {
|
||||
return s.Description
|
||||
}
|
||||
|
||||
func (s *stdin) Input(container lib.Container) (lib.Container, error) {
|
||||
entry := lib.NewEntry(s.Name)
|
||||
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
line, _, _ = strings.Cut(line, "#")
|
||||
line, _, _ = strings.Cut(line, "//")
|
||||
line, _, _ = strings.Cut(line, "/*")
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
switch s.Action {
|
||||
case lib.ActionAdd:
|
||||
if err := entry.AddPrefix(line); err != nil {
|
||||
continue
|
||||
}
|
||||
case lib.ActionRemove:
|
||||
if err := entry.RemovePrefix(line); err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ignoreIPType lib.IgnoreIPOption
|
||||
switch s.OnlyIPType {
|
||||
case lib.IPv4:
|
||||
ignoreIPType = lib.IgnoreIPv6
|
||||
case lib.IPv6:
|
||||
ignoreIPType = lib.IgnoreIPv4
|
||||
}
|
||||
|
||||
if err := container.Add(entry, ignoreIPType); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return container, nil
|
||||
}
|
128
geoip/plugin/special/stdout.go
Normal file
128
geoip/plugin/special/stdout.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package special
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/Loyalsoldier/geoip/lib"
|
||||
)
|
||||
|
||||
const (
|
||||
typeStdout = "stdout"
|
||||
descStdout = "Convert data to plaintext CIDR format and output to standard output"
|
||||
)
|
||||
|
||||
func init() {
|
||||
lib.RegisterOutputConfigCreator(typeStdout, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
||||
return newStdout(action, data)
|
||||
})
|
||||
lib.RegisterOutputConverter(typeStdout, &stdout{
|
||||
Description: descStdout,
|
||||
})
|
||||
}
|
||||
|
||||
func newStdout(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
||||
var tmp struct {
|
||||
Want []string `json:"wantedList"`
|
||||
OnlyIPType lib.IPType `json:"onlyIPType"`
|
||||
}
|
||||
|
||||
if len(data) > 0 {
|
||||
if err := json.Unmarshal(data, &tmp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &stdout{
|
||||
Type: typeStdout,
|
||||
Action: action,
|
||||
Description: descStdout,
|
||||
Want: tmp.Want,
|
||||
OnlyIPType: tmp.OnlyIPType,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type stdout struct {
|
||||
Type string
|
||||
Action lib.Action
|
||||
Description string
|
||||
Want []string
|
||||
OnlyIPType lib.IPType
|
||||
}
|
||||
|
||||
func (s *stdout) GetType() string {
|
||||
return s.Type
|
||||
}
|
||||
|
||||
func (s *stdout) GetAction() lib.Action {
|
||||
return s.Action
|
||||
}
|
||||
|
||||
func (s *stdout) GetDescription() string {
|
||||
return s.Description
|
||||
}
|
||||
|
||||
func (s *stdout) Output(container lib.Container) error {
|
||||
// Filter want list
|
||||
wantList := make(map[string]bool)
|
||||
for _, want := range s.Want {
|
||||
if want = strings.ToUpper(strings.TrimSpace(want)); want != "" {
|
||||
wantList[want] = true
|
||||
}
|
||||
}
|
||||
|
||||
switch len(wantList) {
|
||||
case 0:
|
||||
for entry := range container.Loop() {
|
||||
cidrList, err := s.generateCIDRList(entry)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, cidr := range cidrList {
|
||||
io.WriteString(os.Stdout, cidr+"\n")
|
||||
}
|
||||
}
|
||||
default:
|
||||
for name := range wantList {
|
||||
entry, found := container.GetEntry(name)
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
|
||||
cidrList, err := s.generateCIDRList(entry)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, cidr := range cidrList {
|
||||
io.WriteString(os.Stdout, cidr+"\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stdout) generateCIDRList(entry *lib.Entry) ([]string, error) {
|
||||
var entryList []string
|
||||
var err error
|
||||
switch s.OnlyIPType {
|
||||
case lib.IPv4:
|
||||
entryList, err = entry.MarshalText(lib.IgnoreIPv6)
|
||||
case lib.IPv6:
|
||||
entryList, err = entry.MarshalText(lib.IgnoreIPv4)
|
||||
default:
|
||||
entryList, err = entry.MarshalText()
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(entryList) == 0 {
|
||||
return nil, errors.New("empty CIDR list")
|
||||
}
|
||||
|
||||
return entryList, nil
|
||||
}
|
@@ -81,7 +81,7 @@ func (g *geoIPDatIn) Input(container lib.Container) (lib.Container, error) {
|
||||
var err error
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(g.URI, "http://"), strings.HasPrefix(g.URI, "https://"):
|
||||
case strings.HasPrefix(strings.ToLower(g.URI), "http://"), strings.HasPrefix(strings.ToLower(g.URI), "https://"):
|
||||
err = g.walkRemoteFile(g.URI, entries)
|
||||
default:
|
||||
err = g.walkLocalFile(g.URI, entries)
|
||||
|
Reference in New Issue
Block a user