all repos

viye @ f5220eb9c9864e1616859fb0141dad6cfe5f321a

my shot at reimplementing xiki

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

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