all repos

viye @ fa602cd

my shot at reimplementing xiki

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

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
ip: show only resolved ips, 2 months ago
1
package ip
2
3
import (
4
	"context"
5
	"errors"
6
	"fmt"
7
	"io"
8
	"net"
9
	"net/http"
10
	"strings"
11
	"time"
12
13
	"github.com/olexsmir/viye/internal/viye"
14
)
15
16
type Tool struct{}
17
18
func (Tool) Name() string                 { return "ip" }
19
func (Tool) Match(ctx *viye.Context) bool { return len(ctx.Path) == 1 && ctx.Path[0] == "ip" }
20
func (Tool) Execute(ctx *viye.Context) (string, error) {
21
	pip, perr := getPublicIP()
22
	lip, lerr := getLocalIP()
23
	if perr != nil && lerr != nil {
24
		return "", fmt.Errorf("couldn't resolve public and local ips")
25
	}
26
27
	var buf strings.Builder
28
	_, _ = buf.WriteString("| ")
29
30
	if perr == nil && lerr == nil {
31
		_, _ = buf.WriteString(pip)
32
		_, _ = buf.WriteString(" / ")
33
		_, _ = buf.WriteString(lip)
34
	}
35
36
	if perr == nil && lerr != nil {
37
		_, _ = buf.WriteString(pip)
38
	}
39
40
	if lerr == nil && perr != nil {
41
		_, _ = buf.WriteString(pip)
42
	}
43
44
	_ = buf.WriteByte('\n')
45
	return buf.String(), nil
46
}
47
48
func getLocalIP() (string, error) {
49
	addrs, err := net.InterfaceAddrs()
50
	if err != nil {
51
		return "", err
52
	}
53
	for _, addr := range addrs {
54
		if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
55
			if ipnet.IP.To4() != nil {
56
				return ipnet.IP.String(), nil
57
			}
58
		}
59
	}
60
	return "", errors.New("couldn't get local error")
61
}
62
63
func getPublicIP() (string, error) {
64
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
65
	defer cancel()
66
67
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://ifconfig.me/ip", nil)
68
	if err != nil {
69
		return "", err
70
	}
71
72
	resp, err := http.DefaultClient.Do(req)
73
	if err != nil {
74
		return "", err
75
	}
76
	defer resp.Body.Close()
77
78
	ip, err := io.ReadAll(resp.Body)
79
	if err != nil {
80
		return "", err
81
	}
82
	return strings.TrimSpace(string(ip)), nil
83
}