From 1b16ae243f757da893fc947c2da5f8566cbc9984 Mon Sep 17 00:00:00 2001 From: Leonid Nikitin Date: Wed, 18 Mar 2026 21:03:50 +0500 Subject: [PATCH 1/4] Add support for parsing IPs by version (IPv4 and IPv6) with validation logic --- parser/parser.go | 93 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/parser/parser.go b/parser/parser.go index eb23709..5dc8947 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -11,14 +11,25 @@ import ( type Parser interface { // Parse reads the body and returns a slice of IP addresses. Parse(body io.Reader, validator IPValidator, limit uint) (IPs, error) + + ParseIPsByVersion(body io.Reader, validator IPValidator, limit uint) (ipV4 IPs, ipV6 IPs, err error) } // IPValidator interface defines the contract for validating IP addresses. type IPValidator interface { // IsValid checks if the given IP address is valid. IsValid(ip string) bool + + IsValidAndReturnVersion(ip string) (bool, IPVersion) } +type IPVersion int + +const ( + IPVersion4 IPVersion = iota + IPVersion6 +) + // IPs is a slice of IP addresses. type IPs []string @@ -50,6 +61,48 @@ func (v *DefaultIPValidator) IsValid(value string) bool { return false } +// IsValidAndReturnVersion checks if the given IP address is valid and returns the IP version. +// It returns true if the IP address is not a loopback address and the IP version is either IPv4 or IPv6. +func (v *DefaultIPValidator) IsValidAndReturnVersion(value string) (bool, IPVersion) { + if value == "" { + return false, IPVersion4 + } + + if ip := net.ParseIP(value); ip != nil { + if ip.IsLoopback() { + return false, IPVersion4 + } + + if ip.To4() != nil { + return true, IPVersion4 + } + + if ip.To16() != nil { + return true, IPVersion6 + } + + return false, IPVersion4 + } + + if ip, _, err := net.ParseCIDR(value); err == nil { + if ip.IsLoopback() { + return false, IPVersion4 + } + + if ip.To4() != nil { + return true, IPVersion4 + } + + if ip.To16() != nil { + return true, IPVersion6 + } + + return false, IPVersion4 + } + + return false, IPVersion4 +} + // IPRangeValidator implements IPValidator interface. // It validates IP ranges by parsing them using net.ParseIP and checking if the start and end IPs are in the same network. type IPRangeValidator struct{} @@ -89,3 +142,43 @@ func (v *IPRangeValidator) IsValid(value string) bool { return false } } + +func (v *IPRangeValidator) IsValidAndReturnVersion(value string) (bool, IPVersion) { + if value == "" { + return false, IPVersion4 + } + + parts := strings.Split(value, "-") + if len(parts) != 2 { + return false, IPVersion4 + } + + start := net.ParseIP(strings.TrimSpace(parts[0])) + end := net.ParseIP(strings.TrimSpace(parts[1])) + if start == nil || end == nil { + return false, IPVersion4 + } + + start4 := start.To4() + end4 := end.To4() + + switch { + case start4 != nil && end4 != nil: + if bytes.Compare(start4, end4) <= 0 { + return true, IPVersion4 + } + return false, IPVersion4 + case start4 == nil && end4 == nil: + start16 := start.To16() + end16 := end.To16() + if start16 == nil || end16 == nil { + return false, IPVersion4 + } + if bytes.Compare(start16, end16) <= 0 { + return true, IPVersion6 + } + return false, IPVersion4 + default: + return false, IPVersion4 + } +} From e09411f871c5c6ffadbddeb1096b80e2d7bd7b87 Mon Sep 17 00:00:00 2001 From: Leonid Nikitin Date: Wed, 18 Mar 2026 21:04:33 +0500 Subject: [PATCH 2/4] Add method to parse IPs by version (IPv4/IPv6) with validation and limit support --- parser/json_lines.go | 47 +++++++++++++++++++++++++++++++++++++++++ parser/rss.go | 50 ++++++++++++++++++++++++++++++++++++++++++++ parser/text.go | 46 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) diff --git a/parser/json_lines.go b/parser/json_lines.go index eca1f55..442fc01 100644 --- a/parser/json_lines.go +++ b/parser/json_lines.go @@ -63,3 +63,50 @@ func (p *jsonLinesParser) Parse(body io.Reader, validator IPValidator, limit uin return ips, nil } + +// ParseIPsByVersion parses the JSON Lines data from the given reader +// and returns a slice of IP addresses for each IP version. +// It also returns any errors that occurred during the process. +func (p *jsonLinesParser) ParseIPsByVersion(body io.Reader, validator IPValidator, limit uint) (ipV4 IPs, ipV6 IPs, err error) { + decoder := json.NewDecoder(body) + ipV4 = make(IPs, 0) + ipV6 = make(IPs, 0) + for { + var item json.RawMessage + if err := decoder.Decode(&item); err != nil { + if err == io.EOF { + break + } + return nil, nil, fmt.Errorf("decode json item: %w", err) + } + + if item == nil { + continue + } + + ip, err := p.extract(item) + if err != nil { + return nil, nil, fmt.Errorf("extract ip: %w", err) + } + + ip = strings.TrimSpace(ip) + isValid, ipVersion := validator.IsValidAndReturnVersion(ip) + if !isValid { + continue + } + + if ipVersion == IPVersion4 { + ipV4 = append(ipV4, ip) + } else if ipVersion == IPVersion6 { + ipV6 = append(ipV6, ip) + } else { + continue + } + + if limit > 0 && uint(len(ipV4))+uint(len(ipV6)) >= limit { + break + } + } + + return ipV4, ipV6, nil +} diff --git a/parser/rss.go b/parser/rss.go index c17c150..02c125b 100644 --- a/parser/rss.go +++ b/parser/rss.go @@ -66,3 +66,53 @@ func (p *rssParser) Parse(body io.Reader, validator IPValidator, limit uint) (IP return ips, nil } + +// ParseIPsByVersion parses the RSS data from the given reader +// and returns a slice of IP addresses for each IP version. +// It also returns any errors that occurred during the process. +func (p *rssParser) ParseIPsByVersion(body io.Reader, validator IPValidator, limit uint) (ipV4 IPs, ipV6 IPs, err error) { + decoder := xml.NewDecoder(body) + ipV4 = make(IPs, 0) + ipV6 = make(IPs, 0) + + for { + token, err := decoder.Token() + if err != nil { + if err == io.EOF { + break + } + + return nil, nil, fmt.Errorf("parse rss: %w", err) + } + + start, ok := token.(xml.StartElement) + if !ok { + continue + } + + ip, err := p.extract(decoder, start) + if err != nil { + return nil, nil, fmt.Errorf("extract rss ip: %w", err) + } + + ip = strings.TrimSpace(ip) + isValid, ipVersion := validator.IsValidAndReturnVersion(ip) + if !isValid { + continue + } + + if ipVersion == IPVersion4 { + ipV4 = append(ipV4, ip) + } else if ipVersion == IPVersion6 { + ipV6 = append(ipV6, ip) + } else { + continue + } + + if limit > 0 && uint(len(ipV4))+uint(len(ipV6)) >= limit { + break + } + } + + return ipV4, ipV6, nil +} diff --git a/parser/text.go b/parser/text.go index 528eb5c..80be696 100644 --- a/parser/text.go +++ b/parser/text.go @@ -158,3 +158,49 @@ func (p *textParser) Parse(body io.Reader, validator IPValidator, limit uint) (I return ips, nil } + +func (p *textParser) ParseIPsByVersion(body io.Reader, validator IPValidator, limit uint) (ipV4 IPs, ipV6 IPs, err error) { + ipV4 = make(IPs, 0) + ipV6 = make(IPs, 0) + + scanner := bufio.NewScanner(body) + + buf := make([]byte, 0, 64*1024) + scanner.Buffer(buf, 1024*1024) + + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if line == "" || strings.HasPrefix(line, ";") || strings.HasPrefix(line, "#") { + continue + } + + ip, isFound := p.textExtract.Extract(line) + if !isFound { + continue + } + + ip = strings.TrimSpace(ip) + isValid, ipVersion := validator.IsValidAndReturnVersion(ip) + if !isValid { + continue + } + + if ipVersion == IPVersion4 { + ipV4 = append(ipV4, ip) + } else if ipVersion == IPVersion6 { + ipV6 = append(ipV6, ip) + } else { + continue + } + + if limit > 0 && uint(len(ipV4))+uint(len(ipV6)) >= limit { + break + } + } + + if err := scanner.Err(); err != nil { + return nil, nil, fmt.Errorf("read response: %w", err) + } + + return ipV4, ipV6, nil +} From a2dff48936cf82a4a5b8d3eeb3ac562c7ddc84cd Mon Sep 17 00:00:00 2001 From: Leonid Nikitin Date: Wed, 18 Mar 2026 21:05:11 +0500 Subject: [PATCH 3/4] Refactor request logic with reusable `fetch` function and add methods to handle separated IP parsing for both regular and ZIP responses. --- blocklist.go | 162 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 124 insertions(+), 38 deletions(-) diff --git a/blocklist.go b/blocklist.go index 712029c..9a5df68 100644 --- a/blocklist.go +++ b/blocklist.go @@ -89,29 +89,12 @@ func NewConfigZip(c Config) ConfigZip { // Get fetches data from the given URL, parses the response using the provided parser, and applies the given configuration. // It returns the parsed IPs and any errors that occurred during the process. func Get(fileUrl string, parser parser.Parser, c Config) (parser.IPs, error) { - parsedURL, err := url.Parse(fileUrl) - if err != nil { - return nil, fmt.Errorf("invalid url: %w", err) - } - if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" { - return nil, fmt.Errorf("invalid url scheme: %s", parsedURL.Scheme) - } - ctx, cancel := context.WithTimeout(context.Background(), c.ContextTimeout) defer cancel() - req, err := http.NewRequestWithContext(ctx, http.MethodGet, fileUrl, nil) + res, err := fetch(fileUrl, ctx, c.RequestTimeout) if err != nil { - return nil, fmt.Errorf("create request: %w", err) - } - - client := &http.Client{ - Timeout: c.RequestTimeout, - } - - res, err := client.Do(req) - if err != nil { - return nil, fmt.Errorf("request failed: %w", err) + return nil, err } defer func() { _ = res.Body.Close() @@ -124,32 +107,36 @@ func Get(fileUrl string, parser parser.Parser, c Config) (parser.IPs, error) { return parser.Parse(res.Body, c.Validator, c.Limit) } +// GetSeparatedIPs fetches data from the given URL, parses the response using the provided parser, and applies the given configuration. +// It returns the parsed IPs and any errors that occurred during the process. +func GetSeparatedIPs(fileUrl string, parser parser.Parser, c Config) (ipV4 parser.IPs, ipV6 parser.IPs, err error) { + ctx, cancel := context.WithTimeout(context.Background(), c.ContextTimeout) + defer cancel() + + res, err := fetch(fileUrl, ctx, c.RequestTimeout) + if err != nil { + return nil, nil, err + } + defer func() { + _ = res.Body.Close() + }() + + if res.StatusCode != http.StatusOK { + return nil, nil, fmt.Errorf("unexpected status code: %d", res.StatusCode) + } + + return parser.ParseIPsByVersion(res.Body, c.Validator, c.Limit) +} + // GetZip fetches data from the given URL, parses the response using the provided parser, and applies the given configuration. // It returns the parsed IPs and any errors that occurred during the process. func GetZip(fileUrl string, parser parser.Parser, c ConfigZip) (parser.IPs, error) { - parsedURL, err := url.Parse(fileUrl) - if err != nil { - return nil, fmt.Errorf("invalid url: %w", err) - } - if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" { - return nil, fmt.Errorf("invalid url scheme: %s", parsedURL.Scheme) - } - ctx, cancel := context.WithTimeout(context.Background(), c.Config.ContextTimeout) defer cancel() - req, err := http.NewRequestWithContext(ctx, http.MethodGet, fileUrl, nil) + res, err := fetch(fileUrl, ctx, c.Config.RequestTimeout) if err != nil { - return nil, fmt.Errorf("create request: %w", err) - } - - client := &http.Client{ - Timeout: c.Config.RequestTimeout, - } - - res, err := client.Do(req) - if err != nil { - return nil, fmt.Errorf("request failed: %w", err) + return nil, err } defer func() { _ = res.Body.Close() @@ -184,6 +171,49 @@ func GetZip(fileUrl string, parser parser.Parser, c ConfigZip) (parser.IPs, erro return parseZip(body, parser, c) } +// GetZipSeparatedIPs fetches data from the given URL, parses the response using the provided parser, and applies the given configuration. +// It returns the parsed IPs and any errors that occurred during the process. +func GetZipSeparatedIPs(fileUrl string, parser parser.Parser, c ConfigZip) (ipV4 parser.IPs, ipV6 parser.IPs, err error) { + ctx, cancel := context.WithTimeout(context.Background(), c.Config.ContextTimeout) + defer cancel() + + res, err := fetch(fileUrl, ctx, c.Config.RequestTimeout) + if err != nil { + return nil, nil, err + } + defer func() { + _ = res.Body.Close() + }() + + if res.StatusCode != http.StatusOK { + return nil, nil, fmt.Errorf("unexpected status code: %d", res.StatusCode) + } + + if c.MaxDownloadSize > 0 && res.ContentLength > c.MaxDownloadSize { + return nil, nil, fmt.Errorf("downloaded file is too large: content-length %d exceeds limit %d", res.ContentLength, c.MaxDownloadSize) + } + + reader := res.Body + if c.MaxDownloadSize > 0 { + reader = io.NopCloser(io.LimitReader(res.Body, c.MaxDownloadSize+1)) + } + + body, err := io.ReadAll(reader) + if err != nil { + return nil, nil, fmt.Errorf("read response body: %w", err) + } + + if c.MaxDownloadSize > 0 && int64(len(body)) > c.MaxDownloadSize { + return nil, nil, fmt.Errorf("downloaded file exceeds limit %d bytes", c.MaxDownloadSize) + } + + if !isZip(body) { + return nil, nil, fmt.Errorf("invalid zip archive") + } + + return parseZipSeparatedIPs(body, parser, c) +} + func isZip(body []byte) bool { return len(body) >= 4 && body[0] == 'P' && @@ -223,6 +253,37 @@ func parseZip(body []byte, p parser.Parser, c ConfigZip) (parser.IPs, error) { return p.Parse(zipReader, c.Config.Validator, c.Config.Limit) } +func parseZipSeparatedIPs(body []byte, p parser.Parser, c ConfigZip) (ipV4 parser.IPs, ipV6 parser.IPs, err error) { + reader, err := zip.NewReader(bytes.NewReader(body), int64(len(body))) + if err != nil { + return nil, nil, fmt.Errorf("open zip archive: %w", err) + } + + file := findArchiveFile(reader.File) + if file == nil { + return nil, nil, fmt.Errorf("zip archive does not contain a supported file") + } + + if c.MaxArchiveFileSize > 0 && file.UncompressedSize64 > c.MaxArchiveFileSize { + return nil, nil, fmt.Errorf("file %q in zip is too large: %d exceeds limit %d", file.Name, file.UncompressedSize64, c.MaxArchiveFileSize) + } + + rc, err := file.Open() + if err != nil { + return nil, nil, fmt.Errorf("open file %q from zip: %w", file.Name, err) + } + defer func() { + _ = rc.Close() + }() + + var zipReader io.Reader = rc + if c.MaxArchiveFileSize > 0 { + zipReader = io.LimitReader(rc, int64(c.MaxArchiveFileSize)+1) + } + + return p.ParseIPsByVersion(zipReader, c.Config.Validator, c.Config.Limit) +} + func findArchiveFile(files []*zip.File) *zip.File { var fallback *zip.File @@ -246,3 +307,28 @@ func findArchiveFile(files []*zip.File) *zip.File { return fallback } + +func fetch(fileUrl string, ctx context.Context, requestTimeout time.Duration) (*http.Response, error) { + parsedURL, err := url.Parse(fileUrl) + if err != nil { + return nil, fmt.Errorf("invalid url: %w", err) + } + if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" { + return nil, fmt.Errorf("invalid url scheme: %s", parsedURL.Scheme) + } + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, fileUrl, nil) + if err != nil { + return nil, fmt.Errorf("create request: %w", err) + } + + client := &http.Client{ + Timeout: requestTimeout, + } + + res, err := client.Do(req) + if err != nil { + return nil, fmt.Errorf("request failed: %w", err) + } + return res, nil +} From a8364f98ed6b2ea602af8a1d70de97b57d7e7f5e Mon Sep 17 00:00:00 2001 From: Leonid Nikitin Date: Wed, 18 Mar 2026 21:05:30 +0500 Subject: [PATCH 4/4] Add examples for fetching and displaying separated IPv4 and IPv6 addresses from blocklist services --- examples/blocklist.go | 24 ++++++++++++++++++++++++ examples/bruteforceblocker.go | 12 ++++++++++++ examples/ciarmy.go | 12 ++++++++++++ examples/dshield.go | 24 ++++++++++++++++++++++++ examples/greensnow.go | 12 ++++++++++++ examples/honeypot.go | 12 ++++++++++++ examples/spamhaus.go | 12 ++++++++++++ examples/stopforumspam.go | 12 ++++++++++++ examples/tor.go | 12 ++++++++++++ 9 files changed, 132 insertions(+) diff --git a/examples/blocklist.go b/examples/blocklist.go index a49df63..bbd5a8d 100644 --- a/examples/blocklist.go +++ b/examples/blocklist.go @@ -23,12 +23,24 @@ func main() { // limit 0 - no limit limit := uint(0) config := blocklist.NewConfig(limit) + + // Get IPv4 and IPv6 addresses in one list ips, err := blocklist.Get(url, pars, config) if err != nil { panic(err) } fmt.Println(ips) + // Get IPv4 and IPv6 addresses in two lists + ipsV4, ipsV6, err := blocklist.GetSeparatedIPs(url, pars, config) + if err != nil { + panic(err) + } + fmt.Println("IPv4") + fmt.Println(ipsV4) + fmt.Println("IPv6") + fmt.Println(ipsV6) + /* // This second list retrieves all the IP addresses added in the last 48 hours and is usually a // very large list (over 10000 entries), so be sure that you have the resources available to use it @@ -41,10 +53,22 @@ func main() { // limit 0 - no limit limit := uint(0) config := blocklist.NewConfig(limit) + + // Get IPv4 and IPv6 addresses in one list ips, err := blocklist.Get(url, pars, config) if err != nil { panic(err) } fmt.Println(ips) + + // Get IPv4 and IPv6 addresses in two lists + ipsV4, ipsV6, err := blocklist.GetSeparatedIPs(url, pars, config) + if err != nil { + panic(err) + } + fmt.Println("IPv4") + fmt.Println(ipsV4) + fmt.Println("IPv6") + fmt.Println(ipsV6) */ } diff --git a/examples/bruteforceblocker.go b/examples/bruteforceblocker.go index 51a543b..734ca23 100644 --- a/examples/bruteforceblocker.go +++ b/examples/bruteforceblocker.go @@ -21,9 +21,21 @@ func main() { // limit 0 - no limit limit := uint(0) config := blocklist.NewConfig(limit) + + // Get IPv4 and IPv6 addresses in one list ips, err := blocklist.Get(url, pars, config) if err != nil { panic(err) } fmt.Println(ips) + + // Get IPv4 and IPv6 addresses in two lists + ipsV4, ipsV6, err := blocklist.GetSeparatedIPs(url, pars, config) + if err != nil { + panic(err) + } + fmt.Println("IPv4") + fmt.Println(ipsV4) + fmt.Println("IPv6") + fmt.Println(ipsV6) } diff --git a/examples/ciarmy.go b/examples/ciarmy.go index db1c06b..6885f18 100644 --- a/examples/ciarmy.go +++ b/examples/ciarmy.go @@ -21,9 +21,21 @@ func main() { // limit 0 - no limit limit := uint(0) config := blocklist.NewConfig(limit) + + // Get IPv4 and IPv6 addresses in one list ips, err := blocklist.Get(url, pars, config) if err != nil { panic(err) } fmt.Println(ips) + + // Get IPv4 and IPv6 addresses in two lists + ipsV4, ipsV6, err := blocklist.GetSeparatedIPs(url, pars, config) + if err != nil { + panic(err) + } + fmt.Println("IPv4") + fmt.Println(ipsV4) + fmt.Println("IPv6") + fmt.Println(ipsV6) } diff --git a/examples/dshield.go b/examples/dshield.go index f94d87a..b208627 100644 --- a/examples/dshield.go +++ b/examples/dshield.go @@ -21,12 +21,24 @@ func main() { // limit 0 - no limit limit := uint(0) config := blocklist.NewConfig(limit) + + // Get IPv4 and IPv6 addresses in one list ips, err := blocklist.Get(url, pars, config) if err != nil { panic(err) } fmt.Println(ips) + // Get IPv4 and IPv6 addresses in two lists + ipsV4, ipsV6, err := blocklist.GetSeparatedIPs(url, pars, config) + if err != nil { + panic(err) + } + fmt.Println("IPv4") + fmt.Println(ipsV4) + fmt.Println("IPv6") + fmt.Println(ipsV6) + /* // You can also get a range of IP addresses from this service (from to) url := "https://www.dshield.org/block.txt" @@ -38,10 +50,22 @@ func main() { // limit 0 - no limit limit := uint(0) config := blocklist.NewConfigWithValidator(limit, &parser.IPRangeValidator{}) + + // Get IPv4 and IPv6 addresses in one list ips, err := blocklist.Get(url, pars, config) if err != nil { panic(err) } fmt.Println(ips) + + // Get IPv4 and IPv6 addresses in two lists + ipsV4, ipsV6, err := blocklist.GetSeparatedIPs(url, pars, config) + if err != nil { + panic(err) + } + fmt.Println("IPv4") + fmt.Println(ipsV4) + fmt.Println("IPv6") + fmt.Println(ipsV6) */ } diff --git a/examples/greensnow.go b/examples/greensnow.go index 100512f..ebbd095 100644 --- a/examples/greensnow.go +++ b/examples/greensnow.go @@ -21,9 +21,21 @@ func main() { // limit 0 - no limit limit := uint(0) config := blocklist.NewConfig(limit) + + // Get IPv4 and IPv6 addresses in one list ips, err := blocklist.Get(url, pars, config) if err != nil { panic(err) } fmt.Println(ips) + + // Get IPv4 and IPv6 addresses in two lists + ipsV4, ipsV6, err := blocklist.GetSeparatedIPs(url, pars, config) + if err != nil { + panic(err) + } + fmt.Println("IPv4") + fmt.Println(ipsV4) + fmt.Println("IPv6") + fmt.Println(ipsV6) } diff --git a/examples/honeypot.go b/examples/honeypot.go index 631c1df..dc4a79a 100644 --- a/examples/honeypot.go +++ b/examples/honeypot.go @@ -45,9 +45,21 @@ func main() { // limit 0 - no limit limit := uint(0) config := blocklist.NewConfig(limit) + + // Get IPv4 and IPv6 addresses in one list ips, err := blocklist.Get(url, pars, config) if err != nil { panic(err) } fmt.Println(ips) + + // Get IPv4 and IPv6 addresses in two lists + ipsV4, ipsV6, err := blocklist.GetSeparatedIPs(url, pars, config) + if err != nil { + panic(err) + } + fmt.Println("IPv4") + fmt.Println(ipsV4) + fmt.Println("IPv6") + fmt.Println(ipsV6) } diff --git a/examples/spamhaus.go b/examples/spamhaus.go index 7b96bc8..8b41680 100644 --- a/examples/spamhaus.go +++ b/examples/spamhaus.go @@ -32,9 +32,21 @@ func main() { // limit 0 - no limit limit := uint(0) config := blocklist.NewConfig(limit) + + // Get IPv4 and IPv6 addresses in one list ips, err := blocklist.Get(url, pars, config) if err != nil { panic(err) } fmt.Println(ips) + + // Get IPv4 and IPv6 addresses in two lists + ipsV4, ipsV6, err := blocklist.GetSeparatedIPs(url, pars, config) + if err != nil { + panic(err) + } + fmt.Println("IPv4") + fmt.Println(ipsV4) + fmt.Println("IPv6") + fmt.Println(ipsV6) } diff --git a/examples/stopforumspam.go b/examples/stopforumspam.go index f5118e7..1c3e81b 100644 --- a/examples/stopforumspam.go +++ b/examples/stopforumspam.go @@ -23,9 +23,21 @@ func main() { limit := uint(0) config := blocklist.NewConfig(limit) configZip := blocklist.NewConfigZip(config) + + // Get IPv4 and IPv6 addresses in one list ips, err := blocklist.GetZip(url, pars, configZip) if err != nil { panic(err) } fmt.Println(ips) + + // Get IPv4 and IPv6 addresses in two lists + ipsV4, ipsV6, err := blocklist.GetZipSeparatedIPs(url, pars, configZip) + if err != nil { + panic(err) + } + fmt.Println("IPv4") + fmt.Println(ipsV4) + fmt.Println("IPv6") + fmt.Println(ipsV6) } diff --git a/examples/tor.go b/examples/tor.go index 41f0078..37bedef 100644 --- a/examples/tor.go +++ b/examples/tor.go @@ -21,9 +21,21 @@ func main() { // limit 0 - no limit limit := uint(0) config := blocklist.NewConfig(limit) + + // Get IPv4 and IPv6 addresses in one list ips, err := blocklist.Get(url, pars, config) if err != nil { panic(err) } fmt.Println(ips) + + // Get IPv4 and IPv6 addresses in two lists + ipsV4, ipsV6, err := blocklist.GetSeparatedIPs(url, pars, config) + if err != nil { + panic(err) + } + fmt.Println("IPv4") + fmt.Println(ipsV4) + fmt.Println("IPv6") + fmt.Println(ipsV6) }