all repos

viye @ 63835f54e77ecc1ae8e8ca126fffab519544f58e

my shot at reimplementing xiki

viye/plumbing/ip/ip.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
init, 2 months ago
1
package ip
2
3
import (
4
	"errors"
5
	"io"
6
	"net"
7
	"net/http"
8
	"strings"
9
10
	"github.com/olexsmir/viye/core"
11
)
12
13
type Tool struct{}
14
15
func (Tool) Name() string                 { return "ip" }
16
func (Tool) Match(ctx *core.Context) bool { return len(ctx.Path) == 1 && ctx.Path[0] == "ip" }
17
func (Tool) Execute(ctx *core.Context) (string, error) {
18
	// TODO: if it's not possile to get  public ip, report only local
19
20
	var buf strings.Builder
21
	buf.WriteString("| ")
22
23
	pip, err := getPublicIP()
24
	if err != nil {
25
		return "", err
26
	}
27
	_, _ = buf.WriteString(pip)
28
	_, _ = buf.WriteString(" / ")
29
30
	lip, err := getLocalIP()
31
	if err != nil {
32
		return "", err
33
	}
34
	_, _ = buf.WriteString(lip)
35
36
	_ = buf.WriteByte('\n')
37
	return buf.String(), nil
38
}
39
40
func getLocalIP() (string, error) {
41
	addrs, err := net.InterfaceAddrs()
42
	if err != nil {
43
		return "", err
44
	}
45
	for _, addr := range addrs {
46
		if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
47
			if ipnet.IP.To4() != nil {
48
				return ipnet.IP.String(), nil
49
			}
50
		}
51
	}
52
	return "", errors.New("couldn't get local error")
53
}
54
55
func getPublicIP() (string, error) {
56
	resp, err := http.Get("https://ifconfig.me/ip")
57
	if err != nil {
58
		return "", err
59
	}
60
	defer resp.Body.Close()
61
62
	ip, err := io.ReadAll(resp.Body)
63
	if err != nil {
64
		return "", err
65
	}
66
	return strings.TrimSpace(string(ip)), nil
67
}