Skip to content

Commit c90b4fe

Browse files
authored
Merge pull request #113 from rawnly/f/blurhash
feat: analytics + blur_hash
2 parents 92ce27f + faaf3b1 commit c90b4fe

File tree

13 files changed

+260
-16
lines changed

13 files changed

+260
-16
lines changed

.goreleaser.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ builds:
1414
ldflags:
1515
- -s -w -X "main.ClientId={{ .Env.UNSPLASH_CLIENT_ID }}"
1616
- -s -w -X "main.ClientSecret={{ .Env.UNSPLASH_CLIENT_SECRET }}"
17+
- -s -w -X "main.PostHogKey={{ .Env.POSTHOG_API_KEY }}"
1718
- -s -w -X "main.Debug={{ .Env.DEBUG }}"
1819
- -s -w -X "github.com/rawnly/splash-cli/config.Version={{ .Version }}"
1920
- -s -w -X "github.com/rawnly/splash-cli/config.Commit={{ .Commit }}"

cmd/auth/login.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@ package auth
33
import (
44
"context"
55
"fmt"
6+
"net/http"
7+
"time"
8+
69
"github.com/briandowns/spinner"
710
"github.com/rawnly/splash-cli/lib/console"
811
"github.com/rawnly/splash-cli/lib/keys"
912
"github.com/rawnly/splash-cli/lib/terminal"
1013
"github.com/rawnly/splash-cli/unsplash"
1114
"github.com/spf13/cobra"
1215
"github.com/spf13/viper"
13-
"net/http"
14-
"time"
1516
)
1617

1718
var loginCmd = &cobra.Command{
@@ -49,7 +50,6 @@ var loginCmd = &cobra.Command{
4950

5051
code := <-codeChan
5152
res, err := api.Authenticate(code)
52-
5353
if err != nil {
5454
sp.FinalMSG = "An error occured while authenticating"
5555
sp.Stop()
@@ -81,6 +81,9 @@ var loginCmd = &cobra.Command{
8181
fmt.Println("")
8282
fmt.Println("An error occured while fetching your data.")
8383

84+
viper.Set("user_id", me.Id)
85+
_ = viper.WriteConfig()
86+
8487
cmd.PrintErr(err)
8588
},
8689
}

cmd/root.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/rawnly/splash-cli/cmd/settings"
1818
"github.com/rawnly/splash-cli/config"
1919
"github.com/rawnly/splash-cli/lib"
20+
"github.com/rawnly/splash-cli/lib/blurhash"
2021
"github.com/rawnly/splash-cli/lib/keys"
2122
"github.com/rawnly/splash-cli/lib/terminal"
2223
"github.com/rawnly/splash-cli/unsplash"
@@ -86,6 +87,7 @@ var rootCmd = &cobra.Command{
8687

8788
ctx := cmd.Context()
8889
api := ctx.Value("api").(unsplash.Api)
90+
analytics := keys.GetAnalyticsInstance(ctx)
8991

9092
photoOfTheDayId := viper.GetString("photo-of-the-day.id")
9193

@@ -130,6 +132,8 @@ var rootCmd = &cobra.Command{
130132
cobra.CheckErr(err)
131133

132134
if dayFlag {
135+
analytics.Capture("photo_of_the_day", nil)
136+
133137
if photoOfTheDayId != "" && !ignoreCacheFlag {
134138
photo, err = api.GetPhoto(photoOfTheDayId)
135139
} else {
@@ -153,9 +157,15 @@ var rootCmd = &cobra.Command{
153157
} else if idFlag != "" {
154158
idFlag = lib.ParsePhotoIDFromUrl(idFlag)
155159

160+
analytics.Capture("photo_by_id", map[string]interface{}{
161+
"photo_id": idFlag,
162+
})
163+
156164
photo, err = api.GetPhoto(idFlag)
157165
handleSpinnerError(err, connectionSpinner, cmd, ConnectionSpinnerSuffix[1])
158166
} else {
167+
analytics.Capture("random_photo", nil)
168+
159169
photos, err := api.GetRandomPhoto(models.RandomPhotoParams{
160170
Orientation: orientationFlag,
161171
Query: queryFlag,
@@ -191,6 +201,8 @@ var rootCmd = &cobra.Command{
191201

192202
downloadLocation := fmt.Sprintf("%s/%s.jpg", downloadFolder, photo.Id)
193203

204+
_ = blurhash.Prepare(photo)
205+
194206
var location string
195207

196208
if lib.FileExists(downloadLocation) && !ignoreCacheFlag {

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ go 1.18
55
require (
66
github.com/AlecAivazis/survey/v2 v2.3.4
77
github.com/MakeNowJust/heredoc v1.0.0
8+
github.com/bbrks/go-blurhash v1.1.1
89
github.com/briandowns/spinner v1.18.1
910
github.com/eiannone/keyboard v0.0.0-20200508000154-caf4b762e807
1011
github.com/getsentry/sentry-go v0.24.1
12+
github.com/google/uuid v1.4.0
1113
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d
14+
github.com/posthog/posthog-go v0.0.0-20230801140217-d607812dee69
1215
github.com/rawnly/go-wallpaper v1.0.2
1316
github.com/sirupsen/logrus v1.9.0
1417
github.com/spf13/cast v1.4.1

go.sum

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ
4444
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
4545
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
4646
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
47+
github.com/bbrks/go-blurhash v1.1.1 h1:uoXOxRPDca9zHYabUTwvS4KnY++KKUbwFo+Yxb8ME4M=
48+
github.com/bbrks/go-blurhash v1.1.1/go.mod h1:lkAsdyXp+EhARcUo85yS2G1o+Sh43I2ebF5togC4bAY=
4749
github.com/briandowns/spinner v1.18.1 h1:yhQmQtM1zsqFsouh09Bk/jCjd50pC3EOGsh28gLVvwY=
4850
github.com/briandowns/spinner v1.18.1/go.mod h1:mQak9GHqbspjC/5iUx3qMlIho8xBS/ppAL/hX5SmPJU=
4951
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -54,6 +56,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
5456
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
5557
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
5658
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
59+
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
5760
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
5861
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
5962
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
@@ -131,6 +134,9 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe
131134
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
132135
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
133136
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
137+
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
138+
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
139+
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
134140
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
135141
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
136142
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
@@ -159,6 +165,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
159165
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
160166
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
161167
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
168+
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
169+
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
162170
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
163171
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
164172
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
@@ -184,11 +192,15 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
184192
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
185193
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
186194
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
195+
github.com/posthog/posthog-go v0.0.0-20230801140217-d607812dee69 h1:01dHVodha5BzrMtVmcpPeA4VYbZEsTXQ6m4123zQXJk=
196+
github.com/posthog/posthog-go v0.0.0-20230801140217-d607812dee69/go.mod h1:migYMxlAqcnQy+3eN8mcL0b2tpKy6R+8Zc0lxwk4dKM=
187197
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
188198
github.com/rawnly/go-wallpaper v1.0.2 h1:ttmYCIMwzjuPDTpL7pG9eXjN8PZ3TOVu8wEKO9ojuFA=
189199
github.com/rawnly/go-wallpaper v1.0.2/go.mod h1:qpQ8yj7TK2yZL2YtBjbGf8l0QwtHRwjXfW28j1XjhBs=
190200
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
201+
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
191202
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
203+
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
192204
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
193205
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
194206
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@@ -217,6 +229,7 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
217229
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
218230
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
219231
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
232+
github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
220233
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
221234
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
222235
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=

lib/analytics/analytics.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package analytics
2+
3+
import (
4+
"runtime"
5+
6+
"github.com/AlecAivazis/survey/v2"
7+
"github.com/posthog/posthog-go"
8+
"github.com/rawnly/splash-cli/config"
9+
"github.com/sirupsen/logrus"
10+
"github.com/spf13/viper"
11+
)
12+
13+
type Analytics struct {
14+
client posthog.Client
15+
Enabled bool
16+
}
17+
18+
func New(apiKey string, debug bool) *Analytics {
19+
if apiKey == "YOUR_POSTHOG_KEY" || debug {
20+
return &Analytics{
21+
Enabled: false,
22+
}
23+
}
24+
25+
client, err := posthog.NewWithConfig(
26+
apiKey,
27+
posthog.Config{
28+
Endpoint: "https://eu.posthog.com",
29+
},
30+
)
31+
if err != nil {
32+
logrus.Debug("Error while initializing posthog client: ", err)
33+
return nil
34+
}
35+
36+
return &Analytics{
37+
Enabled: viper.GetBool("user_opt_out_analytics") == false,
38+
client: client,
39+
}
40+
}
41+
42+
func (a *Analytics) Close() error {
43+
if a.client == nil {
44+
return nil
45+
}
46+
47+
return a.client.Close()
48+
}
49+
50+
func (a *Analytics) PromptConsent() bool {
51+
confirm := true
52+
prompt := &survey.Confirm{
53+
Default: true,
54+
Message: "Would you like to help us improve the app by sending anonymous analytics?",
55+
}
56+
57+
if err := survey.AskOne(prompt, &confirm); err != nil {
58+
return false
59+
}
60+
61+
viper.Set("user_opt_out_analytics", !confirm)
62+
a.Enabled = confirm
63+
64+
return confirm
65+
}
66+
67+
func (analytics *Analytics) Capture(event string, properties map[string]interface{}) error {
68+
if !analytics.Enabled {
69+
logrus.Debugf("Analytics disabled skipping event: %s", event)
70+
return nil
71+
}
72+
73+
// default properties
74+
props := posthog.NewProperties().
75+
Set("version", config.GetVersion()).
76+
Set("os", runtime.GOOS).
77+
Set("arch", runtime.GOARCH).
78+
Set("go_version", runtime.Version())
79+
80+
if properties != nil {
81+
for key, value := range properties {
82+
props = props.Set(key, value)
83+
}
84+
}
85+
86+
logrus.Debugf("Capturing event: %s", event)
87+
88+
if err := analytics.client.Enqueue(posthog.Capture{
89+
// TODO: : generate a uuid or use the unsplash id
90+
DistinctId: viper.GetString("user_id"),
91+
Event: event,
92+
Properties: props,
93+
}); err != nil {
94+
panic(err.Error())
95+
}
96+
97+
return nil
98+
}

lib/blurhash/blurhash.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package blurhash
2+
3+
import (
4+
"image/png"
5+
"os"
6+
7+
"github.com/bbrks/go-blurhash"
8+
"github.com/rawnly/go-wallpaper"
9+
"github.com/rawnly/splash-cli/unsplash/models"
10+
"github.com/sirupsen/logrus"
11+
)
12+
13+
func Prepare(photo *models.Photo) error {
14+
w := 1920
15+
h := 1080
16+
punch := 1
17+
18+
img, err := blurhash.Decode(photo.Blurhash, w, h, punch)
19+
if err != nil {
20+
return err
21+
}
22+
23+
file, err := os.CreateTemp("", "splash-cli-hash-*.png")
24+
if err != nil {
25+
return err
26+
}
27+
28+
logrus.Debug("Saving image to ", file.Name())
29+
30+
if err := png.Encode(file, img); err != nil {
31+
defer os.Remove(file.Name())
32+
return err
33+
}
34+
35+
defer file.Close()
36+
37+
if err := wallpaper.SetFromFile(file.Name()); err != nil {
38+
defer os.Remove(file.Name())
39+
logrus.Debug("Error while setting hash wallpaper: ", err)
40+
return err
41+
}
42+
43+
return nil
44+
}

lib/keys/context.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,22 @@ package keys
22

33
import (
44
"context"
5+
6+
"github.com/rawnly/splash-cli/lib/analytics"
57
"github.com/rawnly/splash-cli/unsplash"
68
"github.com/spf13/cast"
79
)
810

911
const (
1012
ApiInstance = "api"
1113
IsLogged = "isLoggedIn"
14+
Analytics = "analytics"
1215
)
1316

17+
func GetAnalyticsInstance(ctx context.Context) *analytics.Analytics {
18+
return ctx.Value(Analytics).(*analytics.Analytics)
19+
}
20+
1421
func GetApiInstance(ctx context.Context) unsplash.Api {
1522
return ctx.Value(ApiInstance).(unsplash.Api)
1623
}

lib/terminal/util.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ package terminal
22

33
import (
44
"fmt"
5-
"github.com/briandowns/spinner"
65
"os"
7-
"os/exec"
86
"strings"
7+
8+
"github.com/briandowns/spinner"
99
)
1010

1111
type Spinner struct {
@@ -35,7 +35,7 @@ func GetEnv() map[string]string {
3535
}
3636

3737
func Clear() {
38-
cmd := exec.Command("clear")
39-
cmd.Stdout = os.Stdout
40-
_ = cmd.Run()
38+
// cmd := exec.Command("clear")
39+
// cmd.Stdout = os.Stdout
40+
// _ = cmd.Run()
4141
}

lib/util.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package lib
22

33
import (
4+
"os/user"
45
"strconv"
56

67
"github.com/rawnly/splash-cli/lib/expressions"
@@ -10,6 +11,23 @@ import (
1011

1112
const AliasViperKey = "aliases"
1213

14+
func GetHomeDir() string {
15+
usr, err := user.Current()
16+
if err != nil {
17+
panic(err)
18+
}
19+
20+
return usr.HomeDir
21+
}
22+
23+
func ExpandPath(path string) string {
24+
if path[:2] == "~/" {
25+
return GetHomeDir() + path[1:]
26+
}
27+
28+
return path
29+
}
30+
1331
func ParseStringValue(value string) any {
1432
if value == "true" || value == "false" {
1533
val, err := strconv.ParseBool(value)
@@ -65,4 +83,3 @@ func SetAlias(name string, value string) error {
6583

6684
return viper.WriteConfig()
6785
}
68-

0 commit comments

Comments
 (0)