Skip to content
This repository was archived by the owner on Dec 21, 2024. It is now read-only.

Commit 48e7042

Browse files
committed
feat: various refactoring
Signed-off-by: Liam Stanley <me@liamstanley.io>
1 parent 71c7a70 commit 48e7042

File tree

3 files changed

+90
-69
lines changed

3 files changed

+90
-69
lines changed

config.go

+16-14
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"os"
1010

11+
"github.com/apex/log"
1112
arlo "github.com/jeffreydwalter/arlo-go"
1213
"github.com/phayes/permbits"
1314
"gopkg.in/AlecAivazis/survey.v1"
@@ -32,26 +33,27 @@ func readConfig(path string) error {
3233
}
3334

3435
if perms := permbits.FileMode(fi.Mode()); perms != 0o600 {
35-
logger.Printf("warning: permissions of %q are insecure: %s, please use 0600", path, perms)
36+
logger.WithFields(log.Fields{
37+
"path": path,
38+
"mode": perms,
39+
}).Warn("permissions of config file are insecure, please use 0600")
3640
}
3741

3842
b, err := os.ReadFile(path)
3943
if err != nil {
4044
return err
4145
}
4246

43-
if err := yaml.Unmarshal(b, conf); err != nil {
47+
err = yaml.Unmarshal(b, conf)
48+
if err != nil {
4449
return err
4550
}
4651
return nil
4752
}
4853

4954
type CommandSetup struct{}
5055

51-
func (cmd *CommandSetup) Execute(args []string) error {
52-
logger.SetFlags(0)
53-
cli.Ensure()
54-
56+
func (cmd *CommandSetup) Execute(_ []string) error {
5557
login:
5658
questions := []*survey.Question{
5759
{
@@ -70,23 +72,23 @@ login:
7072
return err
7173
}
7274

73-
logger.Println("validating login...")
75+
logger.Info("validating login")
7476
if _, err = arlo.Login(conf.Username, conf.Password); err != nil {
75-
logger.Println(err)
76-
logger.Println("please enter new credentials")
77+
logger.WithError(err).Error("failed to login, please enter new credentials")
7778
goto login
7879
}
7980

80-
f, err := os.OpenFile(cli.ConfigFile, os.O_RDWR|os.O_CREATE, 0o600)
81+
f, err := os.OpenFile(cli.Flags.ConfigFile, os.O_RDWR|os.O_CREATE, 0o600)
8182
if err != nil {
82-
logger.Fatalf("error creating %q: %v", cli.ConfigFile, err)
83+
logger.Fatalf("error creating %q: %v", cli.Flags.ConfigFile, err)
8384
}
8485
defer f.Close()
8586

86-
if _, err := fmt.Fprintf(f, "---\nusername: %s\npassword: %s\n", conf.Username, conf.Password); err != nil {
87-
logger.Fatalf("error writing to %q: %v", cli.ConfigFile, err)
87+
_, err = fmt.Fprintf(f, "---\nusername: %s\npassword: %s\n", conf.Username, conf.Password)
88+
if err != nil {
89+
logger.Fatalf("error writing to %q: %v", cli.Flags.ConfigFile, err)
8890
}
89-
logger.Printf("successfully wrote %q", cli.ConfigFile)
9091

92+
logger.WithField("config", cli.Flags.ConfigFile).Info("successfully wrote config")
9193
return nil
9294
}

fetch.go

+46-24
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"text/template"
1212
"time"
1313

14+
"github.com/apex/log"
1415
arlo "github.com/jeffreydwalter/arlo-go"
1516
sempool "github.com/lrstanley/go-sempool"
1617
)
@@ -28,42 +29,50 @@ type RecordingTemplate struct {
2829
}
2930

3031
func fetch() {
31-
logger.Printf("logging into arlo with account: %s", conf.Username)
32+
logger.WithField("account", conf.Username).Info("logging into arlo")
3233
api, err := arlo.Login(conf.Username, conf.Password)
3334
if err != nil {
3435
logger.Fatalf("failed to login: %s\n", err)
3536
}
36-
logger.Println("login successful")
37+
logger.Info("successfully logged in")
3738

3839
cmap := make(map[string]*arlo.Camera)
3940

40-
logger.Println("looking for cameras on account")
41+
logger.Info("looking for cameras on account")
4142
for i := 0; i < len(api.Cameras); i++ {
42-
logger.Printf("found camera %q (id: %s)", api.Cameras[i].DeviceName, api.Cameras[i].DeviceId)
43+
logger.WithFields(log.Fields{
44+
"name": api.Cameras[i].DeviceName,
45+
"id": api.Cameras[i].DeviceId,
46+
}).Info("found camera")
47+
4348
name := reStripName.ReplaceAllString(api.Cameras[i].DeviceName, "_")
4449
name = reTrimUnderscore.ReplaceAllString(name, "_")
4550
name = strings.Trim(name, "_")
4651
if name != api.Cameras[i].DeviceName {
47-
logger.Printf("renaming %q to %q", api.Cameras[i].DeviceName, name)
52+
logger.WithFields(log.Fields{
53+
"old": api.Cameras[i].DeviceName,
54+
"new": name,
55+
}).Info("renaming camera")
56+
4857
api.Cameras[i].DeviceName = name
4958
}
5059

5160
cmap[api.Cameras[i].DeviceId] = &api.Cameras[i]
5261
}
5362

5463
now := time.Now()
55-
start := now.Add(-time.Duration(cli.History) * 24 * time.Hour)
64+
start := now.Add(-time.Duration(cli.Flags.History) * 24 * time.Hour)
5665

57-
logger.Println("fetching library")
66+
logger.Info("fetching library")
5867
library, err := api.GetLibrary(start, now)
5968
if err != nil {
60-
logger.Fatal(err)
69+
logger.WithError(err).Fatal("failed to fetch library")
6170
}
62-
logger.Printf("successfully fetched library; %d items found", len(*library))
71+
logger.WithField("count", len(*library)).Info("successfully fetched library")
6372

64-
pool := sempool.New(cli.MaxConcurrent)
73+
pool := sempool.New(cli.Flags.MaxConcurrent)
6574

66-
for _, recording := range *library {
75+
for _, recording := range *library { // nolint:gocritic
6776
pool.Slot()
6877

6978
go func(r *arlo.Recording) {
@@ -77,34 +86,47 @@ func fetch() {
7786
rtmpl.Timestamp = rtmpl.Time.Format("2006.01.02-15.04.05")
7887

7988
filename := strings.Builder{}
80-
tpl := template.Must(template.New("filename").Parse(cli.NameFormat))
81-
if err := tpl.Execute(&filename, rtmpl); err != nil {
89+
tpl := template.Must(template.New("filename").Parse(cli.Flags.NameFormat))
90+
91+
err = tpl.Execute(&filename, rtmpl)
92+
if err != nil {
8293
logger.Fatalf("error executing filename template for recording %q: %v", r.UniqueId, err)
8394
}
8495

85-
fullFn := filepath.Join(cli.OutputDir, filename.String())
96+
fullFn := filepath.Join(cli.Flags.OutputDir, filename.String())
8697

87-
if err := os.MkdirAll(filepath.Dir(fullFn), 0o755); err != nil {
98+
err = os.MkdirAll(filepath.Dir(fullFn), 0o755)
99+
if err != nil {
88100
logger.Fatalf("error creating dir %q: %v", filepath.Dir(fullFn), err)
89101
}
90102

91-
if _, err := os.Stat(fullFn); err == nil {
92-
logger.Printf("skipping %s/%s, already downloaded", rtmpl.Camera.DeviceName, r.Name)
103+
_, err = os.Stat(fullFn)
104+
if err == nil {
105+
logger.WithFields(log.Fields{
106+
"camera": rtmpl.Camera.DeviceName,
107+
"name": r.Name,
108+
}).Info("skipping, already downloaded")
93109
return
94110
}
95111

96-
f, err := os.Create(fullFn)
112+
var f *os.File
113+
f, err = os.Create(fullFn)
97114
if err != nil {
98-
logger.Fatal(err)
115+
logger.WithError(err).Fatal("failed to create file")
99116
}
100117
defer f.Close()
101118

102-
logger.Printf("streaming recording %s/%s to file: %q", rtmpl.Camera.DeviceName, r.Name, fullFn)
103-
if err := api.DownloadFile(r.PresignedContentUrl, f); err != nil {
104-
logger.Fatal(err)
119+
logger.WithFields(log.Fields{
120+
"camera": rtmpl.Camera.DeviceName,
121+
"name": r.Name,
122+
}).Info("downloading")
123+
124+
err = api.DownloadFile(r.PresignedContentUrl, f)
125+
if err != nil {
126+
logger.WithError(err).Fatal("failed to download file")
105127
}
106-
logger.Printf("finished downloading %q", r.Name)
107-
}(&recording)
128+
logger.WithField("name", r.Name).Info("finished downloading")
129+
}(&recording) // nolint:gosec
108130
}
109131

110132
pool.Wait()

main.go

+28-31
Original file line numberDiff line numberDiff line change
@@ -4,69 +4,66 @@
44
package main
55

66
import (
7-
"fmt"
8-
"io"
9-
"log"
10-
"os"
117
"os/user"
128
"path/filepath"
139

14-
flags "github.com/jessevdk/go-flags"
10+
"github.com/apex/log"
11+
"github.com/lrstanley/clix"
1512
)
1613

17-
var (
14+
const (
1815
version = "master"
1916
commit = "latest"
2017
date = "-"
18+
)
2119

22-
cli = &Flags{}
23-
logger = log.New(os.Stdout, "", log.LstdFlags)
20+
var (
21+
logger log.Interface
22+
cli = &clix.CLI[Flags]{
23+
Links: clix.GithubLinks("github.com/lrstanley/arlo-dl", "master", "https://liam.sh"),
24+
VersionInfo: &clix.VersionInfo[Flags]{
25+
Version: version,
26+
Commit: commit,
27+
Date: date,
28+
},
29+
}
2430
)
2531

2632
type Flags struct {
2733
ConfigFile string `short:"c" long:"config-file" description:"configuration file (see 'arlo-dl setup', default: $HOME/.arlo-dl.yaml)"`
2834
OutputDir string `short:"o" long:"output-dir" description:"location to store recordings" default:"arlo-recordings"`
2935
History int `long:"history" description:"how many days back to download" default:"14"`
30-
Quiet bool `short:"q" long:"quiet" description:"don't log to stdout"`
31-
VersionFlag bool `short:"v" long:"version" description:"display the version of arlo-dl and exit"`
3236
MaxConcurrent int `short:"C" long:"max-concurrent" description:"maximum amount of recordings to download concurrently" default:"2"`
3337
NameFormat string `short:"f" long:"name-format" description:"go-template format for the file name" default:"{{.Camera.DeviceName}}/{{.Time.Year}}/{{.Time.Month}}/{{.Timestamp}}-{{.Recording.Name}}.mp4"`
3438

3539
CommandSetup CommandSetup `command:"setup" description:"generate a config for use with arlo-dl"`
3640
}
3741

3842
func (f *Flags) Ensure() {
39-
if cli.Quiet {
40-
logger.SetOutput(io.Discard)
41-
}
42-
43-
if cli.ConfigFile == "" {
43+
if cli.Flags.ConfigFile == "" {
4444
usr, err := user.Current()
4545
if err != nil {
46-
logger.Fatal(err)
46+
logger.WithError(err).Fatal("failed to get current user")
4747
}
48-
cli.ConfigFile = filepath.Join(usr.HomeDir, ".arlo-dl.yaml")
48+
cli.Flags.ConfigFile = filepath.Join(usr.HomeDir, ".arlo-dl.yaml")
4949
}
5050
}
5151

5252
func main() {
53-
var err error
54-
parser := flags.NewParser(cli, flags.HelpFlag)
55-
parser.SubcommandsOptional = true
56-
if _, err = parser.Parse(); err != nil {
57-
fmt.Fprintln(os.Stderr, err)
58-
os.Exit(1)
59-
}
53+
cli.LoggerConfig.Pretty = true
54+
_ = cli.ParseWithInit(func() error {
55+
logger = cli.Logger
56+
cli.Flags.Ensure()
6057

61-
cli.Ensure()
58+
return nil
59+
}, clix.OptSubcommandsOptional)
6260

63-
if parser.Active != nil {
64-
os.Exit(0)
65-
}
61+
logger = cli.Logger
62+
cli.Flags.Ensure()
6663

67-
logger.Printf("reading config at %q", cli.ConfigFile)
68-
if err = readConfig(cli.ConfigFile); err != nil {
69-
logger.Fatalf("error reading config: %v", err)
64+
logger.WithField("config", cli.Flags.ConfigFile).Info("reading config")
65+
if err := readConfig(cli.Flags.ConfigFile); err != nil {
66+
logger.WithError(err).Fatal("failed to read config")
7067
}
7168

7269
fetch()

0 commit comments

Comments
 (0)