1
0
mirror of https://github.com/taigrr/wtf synced 2025-01-18 04:03:14 -08:00

Merge branch 'finnhub_mod_for_stocks' of github.com:applegreengrape/wtf into applegreengrape-finnhub_mod_for_stocks

This commit is contained in:
Chris Cummer 2020-10-21 21:00:18 -07:00
commit 1dbc28618d
8 changed files with 233 additions and 0 deletions

View File

@ -23,6 +23,7 @@ import (
"github.com/wtfutil/wtf/modules/docker"
"github.com/wtfutil/wtf/modules/exchangerates"
"github.com/wtfutil/wtf/modules/feedreader"
"github.com/wtfutil/wtf/modules/finnhub"
"github.com/wtfutil/wtf/modules/football"
"github.com/wtfutil/wtf/modules/gcal"
"github.com/wtfutil/wtf/modules/gerrit"
@ -308,6 +309,9 @@ func MakeWidget(
case "exchangerates":
settings := exchangerates.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = exchangerates.NewWidget(app, pages, settings)
case "finnhub":
settings := finnhub.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = finnhub.NewWidget(app, settings)
default:
settings := unknown.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = unknown.NewWidget(app, settings)

2
go.mod
View File

@ -25,12 +25,14 @@ require (
github.com/dustin/go-humanize v1.0.0
github.com/gdamore/tcell v1.4.0
github.com/go-ole/go-ole v1.2.4 // indirect
github.com/go-openapi/strfmt v0.19.6 // indirect
github.com/godbus/dbus v4.1.0+incompatible // indirect
github.com/google/go-github/v32 v32.1.0
github.com/gophercloud/gophercloud v0.5.0 // indirect
github.com/hekmon/cunits v2.0.1+incompatible // indirect
github.com/hekmon/transmissionrpc v0.0.0-20190525133028-1d589625bacd
github.com/imdario/mergo v0.3.8 // indirect
github.com/jedib0t/go-pretty v4.3.0+incompatible
github.com/jessevdk/go-flags v1.4.0
github.com/lib/pq v1.2.0 // indirect
github.com/logrusorgru/aurora v0.0.0-20190803045625-94edacc10f9b

14
go.sum
View File

@ -106,6 +106,8 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws/aws-sdk-go v1.19.11 h1:tqaTGER6Byw3QvsjGW0p018U2UOqaJPeJuzoaF7jjoQ=
github.com/aws/aws-sdk-go v1.19.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@ -229,10 +231,15 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-openapi/errors v0.19.2 h1:a2kIyV3w+OS3S97zxUndRVD46+FhGOUBDFY7nmu4CsY=
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
github.com/go-openapi/strfmt v0.19.6 h1:epWc+q5qSgsy7A7+/HYyxLF37vLEYdPSkNB9G8mRqjw=
github.com/go-openapi/strfmt v0.19.6/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk=
github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDAhzyXg+Bs+0Sb4=
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=
@ -388,6 +395,8 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/itsjamie/gin-cors v0.0.0-20160420130702-97b4a9da7933/go.mod h1:AYdLvrSBFloDBNt7Y8xkQ6gmhCODGl8CPikjyIOnNzA=
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PHJzaeDodcfvRAbIo=
github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag=
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
@ -655,6 +664,7 @@ github.com/streadway/amqp v0.0.0-20180528204448-e5adc2ada8b8 h1:l6epF6yBwuejBfhG
github.com/streadway/amqp v0.0.0-20180528204448-e5adc2ada8b8/go.mod h1:1WNBiOZtZQLpVAyu0iTduoJL9hEsMloAK5XWrtW0xdY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@ -667,6 +677,8 @@ github.com/studio-b12/gowebdav v0.0.0-20200303150724-9380631c29a1/go.mod h1:gCcf
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tevino/abool v0.0.0-20170917061928-9b9efcf221b5/go.mod h1:f1SCnEOt6sc3fOJfPQDRDzHOtSXuTtnz0ImG9kPRDV0=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
@ -711,6 +723,8 @@ github.com/zorkian/go-datadog-api v2.29.0+incompatible/go.mod h1:PkXwHX9CUQa/FpB
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.mongodb.org/mongo-driver v1.0.3 h1:GKoji1ld3tw2aC+GX1wbr/J2fX13yNacEYoJ8Nhr0yU=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=

79
modules/finnhub/client.go Normal file
View File

@ -0,0 +1,79 @@
package finnhub
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
)
// Client ..
type Client struct {
symbols []string
apiKey string
}
// NewClient ..
func NewClient(symbols []string, apiKey string) *Client {
client := Client{
symbols: symbols,
apiKey: apiKey,
}
return &client
}
// Getquote ..
func (client *Client) Getquote() ([]Quote, error) {
quotes := []Quote{}
for _, s := range client.symbols {
resp, err := client.finnhubRequest(s)
if err != nil {
return quotes, err
}
var quote Quote
quote.Stock = s
err = json.NewDecoder(resp.Body).Decode(&quote)
if err != nil {
return quotes, err
}
quotes = append(quotes, quote)
}
return quotes, nil
}
/* -------------------- Unexported Functions -------------------- */
var (
finnhubURL = &url.URL{Scheme: "https", Host: "finnhub.io", Path: "/api/v1/quote"}
)
func (client *Client) finnhubRequest(symbol string) (*http.Response, error) {
params := url.Values{}
params.Add("symbol", symbol)
params.Add("token", client.apiKey)
url := finnhubURL.ResolveReference(&url.URL{RawQuery: params.Encode()})
req, err := http.NewRequest("GET", url.String(), nil)
req.Header.Add("Accept", "application/json")
req.Header.Add("Content-Type", "application/json")
if err != nil {
return nil, err
}
httpClient := &http.Client{}
resp, err := httpClient.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode < 200 || resp.StatusCode > 299 {
return nil, fmt.Errorf(resp.Status)
}
return resp, nil
}

View File

@ -0,0 +1,25 @@
package finnhub
import (
"fmt"
"testing"
)
func TestFinnhubClient(t *testing.T) {
testClient := &Client{
symbols: []string{
"AAPL",
"MSFT",
},
apiKey: "",
}
r, err := testClient.Getquote()
if err != nil {
fmt.Println(err)
}
fmt.Println(r[0].Stock, r[0].C)
fmt.Println(r[1].Stock, r[1].C)
}

12
modules/finnhub/quote.go Normal file
View File

@ -0,0 +1,12 @@
package finnhub
type Quote struct {
C float64 `json:"c"`
H float64 `json:"h"`
L float64 `json:"l"`
O float64 `json:"o"`
Pc float64 `json:"pc"`
T int `json:"t"`
Stock string
}

View File

@ -0,0 +1,36 @@
package finnhub
import (
"os"
"github.com/olebedev/config"
"github.com/wtfutil/wtf/cfg"
"github.com/wtfutil/wtf/utils"
)
const (
defaultFocusable = true
defaultTitle = "📈 Stocks Price"
)
// Settings defines the configuration properties for this module
type Settings struct {
common *cfg.Common
apiKey string `help:"Your finnhub API token."`
symbols []string `help:"An array of stocks symbols (i.e. AAPL, MSFT)"`
}
// NewSettingsFromYAML creates a new settings instance from a YAML config block
func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings {
settings := Settings{
common: cfg.NewCommonSettingsFromModule(name, defaultTitle, defaultFocusable, ymlConfig, globalConfig),
apiKey: ymlConfig.UString("apiKey", ymlConfig.UString("apikey", os.Getenv("WTF_FINNHUB_API_KEY"))),
symbols: utils.ToStrs(ymlConfig.UList("symbols")),
}
cfg.ModuleSecret(name, globalConfig, &settings.apiKey).Load()
return &settings
}

61
modules/finnhub/widget.go Normal file
View File

@ -0,0 +1,61 @@
package finnhub
import (
"fmt"
"github.com/jedib0t/go-pretty/table"
"github.com/rivo/tview"
"github.com/wtfutil/wtf/view"
)
// Widget ..
type Widget struct {
view.TextWidget
*Client
settings *Settings
}
// NewWidget ..
func NewWidget(app *tview.Application, settings *Settings) *Widget {
widget := Widget{
TextWidget: view.NewTextWidget(app, settings.common),
Client: NewClient(settings.symbols, settings.apiKey),
settings: settings,
}
return &widget
}
/* -------------------- Exported Functions -------------------- */
func (widget *Widget) Refresh() {
if widget.Disabled() {
return
}
widget.Redraw(widget.content)
}
/* -------------------- Unexported Functions -------------------- */
func (widget *Widget) content() (string, string, bool) {
quotes, err := widget.Client.Getquote()
title := widget.CommonSettings().Title
t := table.NewWriter()
t.AppendHeader(table.Row{"#", "Stock", "Current Price", "Open Price", "Change"})
wrap := false
if err != nil {
wrap = true
} else {
for idx, q := range quotes {
t.AppendRows([]table.Row{
{idx, q.Stock, q.C, q.O, fmt.Sprintf("%.4f", (q.C-q.O)/q.C)},
})
}
}
return title, t.Render(), wrap
}