Skip to content

Commit

Permalink
Merge pull request #47 from goark/develop
Browse files Browse the repository at this point in the history
Add calendar command
  • Loading branch information
spiegel-im-spiegel authored Jun 2, 2024
2 parents 4524cd7 + aa567b8 commit 88fb673
Show file tree
Hide file tree
Showing 15 changed files with 563 additions and 54 deletions.
8 changes: 4 additions & 4 deletions apod/apod.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ func New(ctx context.Context, path, cacheDir string, logger *log.ZapEventLogger)

// read configuration file
if len(path) == 0 {
return fallthroughCfg(cacheDir, repos, logger), nil
return fallthroughCfg(repos, logger), nil
}
file, err := os.Open(path)
if err != nil {
return fallthroughCfg(cacheDir, repos, logger), nil
return fallthroughCfg(repos, logger), nil
}
defer file.Close()
var cfg APOD
Expand All @@ -55,7 +55,7 @@ func New(ctx context.Context, path, cacheDir string, logger *log.ZapEventLogger)
return &cfg, nil
}

func fallthroughCfg(cacheDir string, repos *db.Repository, logger *log.ZapEventLogger) *APOD {
func fallthroughCfg(repos *db.Repository, logger *log.ZapEventLogger) *APOD {
return &APOD{
APIKey: nasaapi.DefaultAPIKey,
logger: logger,
Expand Down Expand Up @@ -90,7 +90,7 @@ func (cfg *APOD) Export(path string) error {
return nil
}

/* Copyright 2023 Spiegel
/* Copyright 2023-2024 Spiegel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
6 changes: 3 additions & 3 deletions apod/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ package apod
import "github.com/ipfs/go-log/v2"

// Register function makes configuration for APOD operations
func Register(apiKey, cacheDir string, logger *log.ZapEventLogger) *APOD {
cfg := fallthroughCfg(cacheDir, nil, logger)
func Register(apiKey string, logger *log.ZapEventLogger) *APOD {
cfg := fallthroughCfg(nil, logger)
if len(apiKey) > 0 {
cfg.APIKey = apiKey
}
return cfg
}

/* Copyright 2023 Spiegel
/* Copyright 2023-2024 Spiegel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
140 changes: 140 additions & 0 deletions calendar/calendar.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package calendar

import (
"fmt"
"io"
"path/filepath"
"strings"
"text/template"
"time"

"github.com/goark/errs"
"github.com/goark/koyomi"
"github.com/goark/koyomi/value"
"github.com/goark/toolbox/ecode"
"github.com/goark/toolbox/tempdir"
)

const defaultTemplate = `{{ range . }}{{ .Date }} {{ .Title }}
{{ end }}`

// Config type is configurations for calendar package.
type Config struct {
start, end value.DateJp
holiday, ephemeris bool
tempDir *tempdir.TempDir
templateFile string
}

// NewConfig function creates new Config instance.
func NewConfig(start, end string, holiday, ephemeris bool, tempDir *tempdir.TempDir, templateFile string) (*Config, error) {
startdate := value.NewDate(time.Time{})
enddate := value.NewDate(time.Time{})
if len(start) == 0 && len(end) == 0 {
tm := time.Now()
startdate = value.NewDateEra(value.EraUnknown, tm.Year(), tm.Month(), 1)
enddate = value.NewDateEra(value.EraUnknown, tm.Year(), tm.Month()+1, 0)
} else {
if len(start) > 0 {
dt, err := value.DateFrom(start)
if err != nil {
return nil, errs.Wrap(err, errs.WithContext("start", start), errs.WithContext("end", end), errs.WithContext("holiday", holiday), errs.WithContext("ephemeris", ephemeris), errs.WithContext("templateFile", templateFile))
}
startdate = dt
}
if len(start) > 0 {
dt, err := value.DateFrom(end)
if err != nil {
return nil, errs.Wrap(err, errs.WithContext("start", start), errs.WithContext("end", end), errs.WithContext("holiday", holiday), errs.WithContext("ephemeris", ephemeris), errs.WithContext("templateFile", templateFile))
}
enddate = dt
}
}
return &Config{
start: startdate,
end: enddate,
holiday: holiday,
ephemeris: ephemeris,
tempDir: tempDir,
templateFile: templateFile,
}, nil
}

func (cal *Config) OutputEvent(w io.Writer) error {
if cal == nil {
return errs.Wrap(ecode.ErrNullPointer)
}
evs, err := cal.GetEvents()
if err != nil {
return errs.Wrap(err)
}

var tpl *template.Template
if len(cal.templateFile) > 0 {
t, err := template.New(filepath.Base(cal.templateFile)).ParseFiles(cal.templateFile)
if err != nil {
return errs.Wrap(err, errs.WithContext("templateFile", cal.templateFile))
}
tpl = t
} else {
t, err := template.New("").Parse(defaultTemplate)
if err != nil {
return errs.Wrap(err, errs.WithContext("defaultTemplate", defaultTemplate))
}
tpl = t
}
if err := tpl.Execute(w, evs); err != nil {
return errs.Wrap(err)
}
return nil
}

func OutputEventSimple(evs []koyomi.Event) string {
b := strings.Builder{}
for _, ev := range evs {
b.WriteString(fmt.Sprintln(ev.Date, ev.Title))
}
return b.String()
}

// GetEvents method returns astronomical events.
func (cal *Config) GetEvents() ([]koyomi.Event, error) {
if cal == nil {
return nil, errs.Wrap(ecode.ErrNullPointer)
}
ids := []koyomi.CalendarID{}
if cal.holiday {
ids = append(ids, koyomi.Holiday)
}
if cal.ephemeris {
ids = append(ids, koyomi.MoonPhase, koyomi.SolarTerm, koyomi.Eclipse, koyomi.Planet)
}
if len(ids) == 0 {
return []koyomi.Event{}, nil
}
k, err := koyomi.NewSource(
koyomi.WithCalendarID(ids...),
koyomi.WithStartDate(cal.start),
koyomi.WithEndDate(cal.end),
koyomi.WithTempDir(cal.tempDir.Path()),
).Get()
if err != nil {
return nil, errs.Wrap(err)
}
return k.Events(), nil
}

/* Copyright 2024 Spiegel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Binary file modified dependency.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion facade/apod-lookup.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func newAPODLookupCmd(ui *rwi.RWI) *cobra.Command {
apodLookupCmd := &cobra.Command{
Use: "lookup",
Aliases: []string{"look", "l"},
Short: "Lookup APOD data NASA API key",
Short: "Lookup APOD data by NASA API",
Long: "Lookup Astronomy Picture of the Day data.",
RunE: func(cmd *cobra.Command, args []string) error {
// Global options
Expand Down
4 changes: 2 additions & 2 deletions facade/apod-register.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func newAPODRegisterCmd(ui *rwi.RWI) *cobra.Command {
if err != nil {
return debugPrint(ui, err)
}
mcfg := apod.Register(apiKey, gopts.CacheDir, gopts.Logger)
mcfg := apod.Register(apiKey, gopts.Logger)
if err := debugPrint(ui, mcfg.Export(gopts.apodConfigPath)); err != nil {
return debugPrint(ui, err)
}
Expand All @@ -58,7 +58,7 @@ func getAPODAPIKey(ctx context.Context) (string, error) {
}
}

/* Copyright 2023 Spiegel
/* Copyright 2023-2024 Spiegel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
48 changes: 48 additions & 0 deletions facade/calendar-lookup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package facade

import (
"github.com/goark/gocli/rwi"
"github.com/spf13/cobra"
)

// newCalendarLookupCmd returns cobra.Command instance for show sub-command
func newCalendarLookupCmd(ui *rwi.RWI) *cobra.Command {
calendarLookupCmd := &cobra.Command{
Use: "lookup",
Aliases: []string{"look", "l"},
Short: "Lookup astronomical calendar",
Long: "Lookup astronomical calendar.",
RunE: func(cmd *cobra.Command, args []string) error {
// Global options
gopts, err := getGlobalOptions()
if err != nil {
return debugPrint(ui, err)
}
// local options
ccfg, err := getCalendarConfig(cmd, gopts)
if err != nil {
return debugPrint(ui, err)
}

// lookup calendar data
return debugPrint(ui, ccfg.OutputEvent(ui.Writer()))
},
}

return calendarLookupCmd
}

/* Copyright 2024 Spiegel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
110 changes: 110 additions & 0 deletions facade/calendar-post.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package facade

import (
"bytes"
"errors"

"github.com/goark/errs"
"github.com/goark/errs/zapobject"
"github.com/goark/gocli/rwi"
"github.com/goark/toolbox/bluesky"
"github.com/goark/toolbox/mastodon"
"github.com/spf13/cobra"
"go.uber.org/zap"
)

// newCalendarPostCmd returns cobra.Command instance for show sub-command
func newCalendarPostCmd(ui *rwi.RWI) *cobra.Command {
calendarPostCmd := &cobra.Command{
Use: "post",
Aliases: []string{"pst", "p"},
Short: "Post astronomical calendar data to TL",
Long: "Post astronomical calendar data to time lines.",
RunE: func(cmd *cobra.Command, args []string) error {
// Global options
gopts, err := getGlobalOptions()
if err != nil {
return debugPrint(ui, err)
}
// local options
ccfg, err := getCalendarConfig(cmd, gopts)
if err != nil {
return debugPrint(ui, err)
}
bskyFlag, err := cmd.Flags().GetBool("bluesky")
if err != nil {
return debugPrint(ui, err)
}
mastodonFlag, err := cmd.Flags().GetBool("mastodon")
if err != nil {
return debugPrint(ui, err)
}

// lookup calendar data
b := &bytes.Buffer{}
if err := ccfg.OutputEvent(b); err != nil {
gopts.Logger.Error("error in calendar.Config.OutputEvent", zap.Object("error", zapobject.New(err)))
return debugPrint(ui, err)
}
msg := b.String()

var lastErrs []error

// post to Bluesky
if bskyFlag {
wp, err := gopts.getWebpage(cmd.Context())
if err != nil {
return debugPrint(ui, err)
}
if bsky, err := gopts.getBluesky(wp); err != nil {
gopts.Logger.Info("no Bluesky configuration", zap.Object("error", zapobject.New(err)))
lastErrs = append(lastErrs, err)
} else if resText, err := bsky.PostMessage(cmd.Context(), &bluesky.Message{Msg: msg, ImageFiles: nil}); err != nil {
bsky.Logger().Error("error in bluesky.PostMessage", zap.Object("error", zapobject.New(err)))
lastErrs = append(lastErrs, err)
} else {
_ = ui.Outputln("post to Bluesky:", resText)
}
}
// post to Mastodon
if mastodonFlag {
if mstdn, err := gopts.getMastodon(); err != nil {
gopts.Logger.Info("no Mastodon configuration", zap.Object("error", zapobject.New(err)))
lastErrs = append(lastErrs, err)
} else if resText, err := mstdn.PostMessage(cmd.Context(), &mastodon.Message{
Msg: msg,
ImageFiles: nil,
}); err != nil {
mstdn.Logger().Error("error in mastodon.PostMessage", zap.Object("error", zapobject.New(err)))
lastErrs = append(lastErrs, err)
} else {
_ = ui.Outputln("post to Mastodon:", resText)
}
}

if len(lastErrs) > 0 {
return debugPrint(ui, errs.Wrap(errors.Join(lastErrs...)))
}
return nil
},
}
calendarPostCmd.Flags().BoolP("bluesky", "b", false, "Post to bluesky")
calendarPostCmd.Flags().BoolP("mastodon", "m", false, "Post to Mastodon")

return calendarPostCmd
}

/* Copyright 2024 Spiegel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Loading

0 comments on commit 88fb673

Please sign in to comment.