feat(ipify): segment to show your external IP address

closes #1492
This commit is contained in:
Robbert Verbruggen 2021-12-23 14:58:18 +01:00 committed by Jan De Dobbeleer
parent 469745dd95
commit b245398661
6 changed files with 227 additions and 1 deletions

View file

@ -0,0 +1,45 @@
---
id: ipify
title: Ipify
sidebar_label: Ipify
---
## What
[Ipify][ipify] is a simple Public IP Address API, it returns your public IP Adress in plain text.
## Sample Configuration
```json
{
"type": "ipify",
"style": "diamond",
"foreground": "#ffffff",
"background": "#c386f1",
"leading_diamond": "",
"trailing_diamond": "\uE0B0",
"properties": {
"template": "{{ .IP }}",
"cache_timeout": 5,
"http_timeout": 1000
}
}
```
## Properties
- url: `string` - The Ipify URL, by default IPv4 is used, use `https://api64.ipify.org` for IPv6 - defaults to `https://api.ipify.org`
- http_timeout: `int` - How long may the segment wait for a response of the ipify API? -
defaults to 20ms
- cache_timeout: `int` in minutes - How long do you want your IP address cached? -
defaults to 10 min
- template: `string` - a go [text/template][go-text-template] template extended
with [sprig][sprig] utilizing the properties below. - defaults to `{{ .IP }}`
## Template Properties
- .IP: `string` - Your external IP address
[go-text-template]: https://golang.org/pkg/text/template/
[sprig]: https://masterminds.github.io/sprig/
[ipify]: https://www.ipify.org/

View file

@ -52,6 +52,7 @@ module.exports = {
"git",
"poshgit",
"golang",
"ipify",
"java",
"julia",
"kubectl",

View file

@ -141,6 +141,8 @@ const (
WinReg SegmentType = "winreg"
// Brewfather segment
BrewFather SegmentType = "brewfather"
// Ipify segment
Ipify SegmentType = "ipify"
)
func (segment *Segment) string() string {
@ -274,6 +276,7 @@ func (segment *Segment) mapSegmentWithWriter(env environmentInfo) error {
WiFi: &wifi{},
WinReg: &winreg{},
BrewFather: &brewfather{},
Ipify: &ipify{},
}
if segment.Properties == nil {
segment.Properties = make(properties)

72
src/segment_ipify.go Normal file
View file

@ -0,0 +1,72 @@
package main
type ipify struct {
props properties
env environmentInfo
IP string
}
const (
IpifyURL Property = "url"
)
func (i *ipify) enabled() bool {
ip, err := i.getResult()
if err != nil {
return false
}
i.IP = ip
return true
}
func (i *ipify) string() string {
segmentTemplate := i.props.getString(SegmentTemplate, "{{.IP}}")
template := &textTemplate{
Template: segmentTemplate,
Context: i,
Env: i.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
}
func (i *ipify) getResult() (string, error) {
cacheTimeout := i.props.getInt(CacheTimeout, DefaultCacheTimeout)
url := i.props.getString(IpifyURL, "https://api.ipify.org")
if cacheTimeout > 0 {
// check if data stored in cache
val, found := i.env.cache().get(url)
// we got something from te cache
if found {
return val, nil
}
}
httpTimeout := i.props.getInt(HTTPTimeout, DefaultHTTPTimeout)
body, err := i.env.doGet(url, httpTimeout)
if err != nil {
return "", err
}
// convert the body to a string
response := string(body)
if cacheTimeout > 0 {
// persist public ip in cache
i.env.cache().set(url, response, cacheTimeout)
}
return response, nil
}
func (i *ipify) init(props properties, env environmentInfo) {
i.props = props
i.env = env
}

69
src/segment_ipify_test.go Normal file
View file

@ -0,0 +1,69 @@
package main
import (
"errors"
"testing"
"github.com/stretchr/testify/assert"
)
const (
IPIFYAPIURL = "https://api.ipify.org"
)
func TestIpifySegment(t *testing.T) {
cases := []struct {
Case string
Response string
ExpectedString string
ExpectedEnabled bool
Template string
Error error
}{
{
Case: "IPv4",
Response: `127.0.0.1`,
ExpectedString: "127.0.0.1",
ExpectedEnabled: true,
},
{
Case: "IPv6 (with template)",
Response: `0000:aaaa:1111:bbbb:2222:cccc:3333:dddd`,
ExpectedString: "Ext. IP: 0000:aaaa:1111:bbbb:2222:cccc:3333:dddd",
ExpectedEnabled: true,
Template: "Ext. IP: {{.IP}}",
},
{
Case: "Error in retrieving data",
Response: "nonsense",
Error: errors.New("Something went wrong"),
ExpectedEnabled: false,
},
}
for _, tc := range cases {
env := &MockedEnvironment{}
var props properties = map[Property]interface{}{
CacheTimeout: 0,
}
env.On("doGet", IPIFYAPIURL).Return([]byte(tc.Response), tc.Error)
if tc.Template != "" {
props[SegmentTemplate] = tc.Template
}
o := &ipify{
props: props,
env: env,
}
enabled := o.enabled()
assert.Equal(t, tc.ExpectedEnabled, enabled, tc.Case)
if !enabled {
continue
}
assert.Equal(t, tc.ExpectedString, o.string(), tc.Case)
}
}

View file

@ -184,7 +184,8 @@
"wakatime",
"wifi",
"winreg",
"plastic"
"plastic",
"ipify"
]
},
"style": {
@ -1926,6 +1927,41 @@
}
}
}
},
{
"if": {
"properties": {
"type": { "const": "ipify" }
}
},
"then": {
"title": "Display your external IP Address",
"description": "https://ohmyposh.dev/docs/ipify",
"properties": {
"properties": {
"properties": {
"url": {
"type": "string",
"title": "URL",
"description": "The Ipify API URL",
"default": "https://api.ipify.org"
},
"http_timeout": {
"$ref": "#/definitions/http_timeout"
},
"cache_timeout": {
"type": "integer",
"title": "cache timeout",
"description": "The number of minutes the response is cached. A value of 0 disables the cache.",
"default": 10
},
"template": {
"$ref": "#/definitions/template"
}
}
}
}
}
}
]
}