summaryrefslogtreecommitdiff
path: root/plugin/special/lookup.go
blob: 25dd25214ae75a01f156a1e9cc028b5787066b1a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package special

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/netip"
	"slices"
	"strings"

	"github.com/Loyalsoldier/geoip/lib"
)

const (
	TypeLookup = "lookup"
	DescLookup = "Lookup specified IP or CIDR from various formats of data"
)

func init() {
	lib.RegisterOutputConfigCreator(TypeLookup, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
		return NewLookupFromBytes(action, data)
	})
	lib.RegisterOutputConverter(TypeLookup, &lookup{
		Description: DescLookup,
	})
}

func NewLookup(action lib.Action, opts ...lib.OutputOption) lib.OutputConverter {
	l := &lookup{
		Type:        TypeLookup,
		Action:      action,
		Description: DescLookup,
	}

	for _, opt := range opts {
		if opt != nil {
			opt(l)
		}
	}

	return l
}

func WithLookupSearch(search string) lib.OutputOption {
	return func(l lib.OutputConverter) {
		l.(*lookup).Search = strings.TrimSpace(search)
	}
}

func WithLookupSearchList(searchList []string) lib.OutputOption {
	return func(l lib.OutputConverter) {
		l.(*lookup).SearchList = searchList
	}
}

func NewLookupFromBytes(action lib.Action, data []byte) (lib.OutputConverter, error) {
	var tmp struct {
		Search     string   `json:"search"`
		SearchList []string `json:"searchList"`
	}

	if len(data) > 0 {
		if err := json.Unmarshal(data, &tmp); err != nil {
			return nil, err
		}
	}

	tmp.Search = strings.TrimSpace(tmp.Search)
	if tmp.Search == "" {
		return nil, fmt.Errorf("❌ [type %s | action %s] please specify an IP or a CIDR as search target", TypeLookup, action)
	}

	return NewLookup(
		action,
		WithLookupSearch(tmp.Search),
		WithLookupSearchList(tmp.SearchList),
	), nil
}

type lookup struct {
	Type        string
	Action      lib.Action
	Description string
	Search      string
	SearchList  []string
}

func (l *lookup) GetType() string {
	return l.Type
}

func (l *lookup) GetAction() lib.Action {
	return l.Action
}

func (l *lookup) GetDescription() string {
	return l.Description
}

func (l *lookup) Output(container lib.Container) error {
	switch strings.Contains(l.Search, "/") {
	case true: // CIDR
		if _, err := netip.ParsePrefix(l.Search); err != nil {
			return errors.New("invalid IP or CIDR")
		}

	case false: // IP
		if _, err := netip.ParseAddr(l.Search); err != nil {
			return errors.New("invalid IP or CIDR")
		}
	}

	lists, found, _ := container.Lookup(l.Search, l.SearchList...)
	if found {
		slices.Sort(lists)
		fmt.Println(strings.ToLower(strings.Join(lists, ",")))
	} else {
		fmt.Println("false")
	}

	return nil
}